import DesignSystem
import Models
import Network
import SwiftUI

@MainActor
public class AppAccountViewModel: ObservableObject {
  private static var avatarsCache: [String: UIImage] = [:]
  private static var accountsCache: [String: Account] = [:]

  var appAccount: AppAccount
  let client: Client
  let isCompact: Bool

  @Published var account: Account? {
    didSet {
      if let account {
        refreshAcct(account: account)
      }
    }
  }

  @Published var roundedAvatar: UIImage?

  var acct: String {
    if let acct = appAccount.accountName {
      return acct
    } else {
      return "@\(account?.acct ?? "...")@\(appAccount.server)"
    }
  }

  public init(appAccount: AppAccount, isCompact: Bool = false) {
    self.appAccount = appAccount
    self.isCompact = isCompact
    client = .init(server: appAccount.server, oauthToken: appAccount.oauthToken)
  }

  func fetchAccount() async {
    do {
      account = Self.accountsCache[appAccount.id]
      roundedAvatar = Self.avatarsCache[appAccount.id]

      account = try await client.get(endpoint: Accounts.verifyCredentials)
      Self.accountsCache[appAccount.id] = account

      if let account {
        await refreshAvatar(account: account)
      }

    } catch {}
  }

  private func refreshAcct(account: Account) {
    do {
      if appAccount.accountName == nil {
        appAccount.accountName = "\(account.acct)@\(appAccount.server)"
        try appAccount.save()
      }
    } catch {}
  }

  private func refreshAvatar(account: Account) async {
    if let (data, _) = try? await URLSession.shared.data(from: account.avatar),
       let image = UIImage(data: data)?.roundedImage
    {
      roundedAvatar = image
      Self.avatarsCache[account.id] = image
    }
  }
}
