import SwiftUI

struct AccountEditorView: View {
    @Environment(\.dismiss) private var dismiss
    @EnvironmentObject private var accountStore: AccountStore
    let account: Account?

    @State private var name = ""
    @State private var currencyCode = AppSettings.getOrCreate(in: CoreDataStack.shared.viewContext).currency
    @State private var inputMode: InputMode = .simple
    @State private var notificationFrequency: NotificationFrequency = .monthly
    @State private var customFrequencyMonths = 1
    @State private var errorMessage: String?

    private let accountRepository = AccountRepository()

    var body: some View {
        NavigationStack {
            Form {
                Section {
                    if isEditingDefaultAccount {
                        HStack {
                            Text(Account.defaultAccountName)
                                .foregroundColor(.secondary)
                            Spacer()
                            Image(systemName: "lock.fill")
                                .font(.caption)
                                .foregroundColor(.secondary)
                        }
                    } else {
                        TextField("Account name", text: $name)
                    }
                    Picker("Currency", selection: $currencyCode) {
                        ForEach(CurrencyPicker.commonCodes, id: \.self) { code in
                            Text(code).tag(code)
                        }
                    }
                } header: {
                    Text("Account")
                } footer: {
                    if let errorMessage {
                        Text(errorMessage)
                            .foregroundColor(.negativeRed)
                    } else if isEditingDefaultAccount {
                        Text("The Default account name cannot be changed.")
                    }
                }

                Section {
                    Picker("Input Mode", selection: $inputMode) {
                        ForEach(InputMode.allCases) { mode in
                            Text(mode.title).tag(mode)
                        }
                    }
                } header: {
                    Text("Input")
                } footer: {
                    Text(inputMode.description)
                }

            }
            .navigationTitle(account == nil ? "New Account" : "Edit Account")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button("Cancel") { dismiss() }
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button("Save") { saveAccount() }
                        .disabled(!isValid)
                }
            }
            .onAppear {
                loadAccount()
            }
            .onChange(of: name) { _, _ in
                validateName()
            }
        }
        .presentationDetents([.large])
    }

    private var isEditingDefaultAccount: Bool {
        account?.isDefaultAccount == true
    }

    private var isValid: Bool {
        if isEditingDefaultAccount {
            return true // Can only edit currency/inputMode for Default account
        }
        let trimmed = name.trimmingCharacters(in: .whitespaces)
        return !trimmed.isEmpty && errorMessage == nil
    }

    private func validateName() {
        let trimmed = name.trimmingCharacters(in: .whitespaces)
        if trimmed.isEmpty {
            errorMessage = nil
            return
        }

        // Check if trying to use reserved "Default" name for a non-default account
        if trimmed.lowercased() == Account.defaultAccountName.lowercased() {
            let isCreatingNew = account == nil
            let isEditingNonDefault = account != nil && !account!.isDefaultAccount
            if isCreatingNew || isEditingNonDefault {
                errorMessage = "The name '\(Account.defaultAccountName)' is reserved."
                return
            }
        }

        // Check for duplicate names
        if !accountRepository.isNameAvailable(trimmed, excludingAccountId: account?.safeId) {
            errorMessage = "An account with this name already exists."
            return
        }

        errorMessage = nil
    }

    private func loadAccount() {
        guard let account else { return }
        name = account.name
        currencyCode = account.currencyCode ?? currencyCode
        inputMode = InputMode(rawValue: account.inputMode) ?? .simple
        notificationFrequency = .monthly
        customFrequencyMonths = 1
        validateName()
    }

    private func saveAccount() {
        if !isEditingDefaultAccount {
            validateName()
            guard errorMessage == nil else { return }
        }
        let trimmedName = isEditingDefaultAccount ? Account.defaultAccountName : name.trimmingCharacters(in: .whitespaces)
        let enforcedFrequency: NotificationFrequency = .monthly
        let enforcedCustomMonths = 1
        if let account {
            accountRepository.updateAccount(
                account,
                name: isEditingDefaultAccount ? nil : trimmedName, // Don't update name for Default account
                currency: currencyCode,
                inputMode: inputMode,
                notificationFrequency: enforcedFrequency,
                customFrequencyMonths: enforcedCustomMonths
            )
        } else {
            _ = accountRepository.createAccount(
                name: trimmedName,
                currency: currencyCode,
                inputMode: inputMode,
                notificationFrequency: enforcedFrequency,
                customFrequencyMonths: enforcedCustomMonths
            )
        }

        accountStore.persistSelection()
        dismiss()
    }
}

#Preview {
    AccountEditorView(account: nil)
        .environmentObject(AccountStore(iapService: IAPService()))
}
