import Foundation
import Combine
import CoreData

@MainActor
class AccountStore: ObservableObject {
    @Published private(set) var accounts: [Account] = []
    @Published var selectedAccount: Account?
    @Published var showAllAccounts = true

    private let accountRepository: AccountRepository
    private let iapService: IAPService
    private var cancellables = Set<AnyCancellable>()

    init(
        accountRepository: AccountRepository? = nil,
        iapService: IAPService
    ) {
        self.accountRepository = accountRepository ?? AccountRepository()
        self.iapService = iapService

        // Clean up any duplicate Default accounts from previous bug
        self.accountRepository.cleanupDuplicateDefaultAccounts()

        // Create default account if needed (now fetches directly from DB)
        let defaultAccount = self.accountRepository.createDefaultAccountIfNeeded()

        // Trigger async fetch to populate the published accounts array
        self.accountRepository.fetchAccounts()
        accounts = self.accountRepository.accounts
        selectedAccount = defaultAccount

        loadSelection()
        setupObservers()
    }

    private func setupObservers() {
        accountRepository.$accounts
            .receive(on: DispatchQueue.main)
            .sink { [weak self] accounts in
                self?.accounts = accounts
                if let selected = self?.selectedAccount, selected.isDeleted {
                    self?.selectedAccount = nil
                }
                self?.syncSelectedAccount()
            }
            .store(in: &cancellables)

        NotificationCenter.default.publisher(for: .didResetData)
            .receive(on: DispatchQueue.main)
            .sink { [weak self] _ in
                guard let self else { return }
                self.accountRepository.fetchAccounts()
                self.selectedAccount = nil
                self.showAllAccounts = true
                self.persistSelection()
            }
            .store(in: &cancellables)
    }

    private func loadSelection() {
        let context = CoreDataStack.shared.viewContext
        let settings = AppSettings.getOrCreate(in: context)
        showAllAccounts = settings.showAllAccounts

        if let selectedId = settings.selectedAccountId,
           let account = accountRepository.fetchAccount(by: selectedId) {
            selectedAccount = account
        } else {
            selectedAccount = accounts.first
        }
    }

    private func syncSelectedAccount() {
        if showAllAccounts { return }
        if let selectedId = selectedAccount?.safeId,
           accounts.contains(where: { $0.safeId == selectedId }) {
            return
        }
        selectedAccount = accounts.first
    }

    func selectAllAccounts() {
        showAllAccounts = true
        selectedAccount = nil
        persistSelection()
    }

    func selectAccount(_ account: Account) {
        showAllAccounts = false
        selectedAccount = account
        persistSelection()
    }

    func persistSelection() {
        let context = CoreDataStack.shared.viewContext
        let settings = AppSettings.getOrCreate(in: context)
        settings.showAllAccounts = showAllAccounts
        settings.selectedAccountId = showAllAccounts ? nil : selectedAccount?.safeId
        CoreDataStack.shared.save()
    }

    func canAddAccount() -> Bool {
        iapService.isPremium || accounts.count < 1
    }
}

extension Account {
    var safeId: UUID? {
        guard !isDeleted else { return nil }
        return value(forKey: "id") as? UUID
    }
}
