import Foundation
import ComposeApp
import Combine

enum PasswordResetStep: CaseIterable {
    case requestCode    // Step 1: Enter email
    case verifyCode     // Step 2: Enter 6-digit code
    case resetPassword  // Step 3: Set new password
    case loggingIn      // Auto-login in progress
    case success        // Final: Success confirmation (only used if auto-login fails)
}

/// ViewModel for password reset flow.
/// Calls APILayer directly for all password reset operations.
@MainActor
class PasswordResetViewModel: ObservableObject {
    // MARK: - Published Properties
    @Published var email: String = ""
    @Published var code: String = ""
    @Published var newPassword: String = ""
    @Published var confirmPassword: String = ""
    @Published var isLoading: Bool = false
    @Published var errorMessage: String?
    @Published var successMessage: String?
    @Published var currentStep: PasswordResetStep = .requestCode
    @Published var resetToken: String?

    // Callback for successful login after password reset
    var onLoginSuccess: ((Bool) -> Void)?

    // Cancellable delayed transition task
    private var delayedTransitionTask: Task<Void, Never>?

    // MARK: - Private Properties
    private let dataManager: DataManagerObservable

    // MARK: - Initialization
    init(
        resetToken: String? = nil,
        dataManager: DataManagerObservable = .shared
    ) {
        self.dataManager = dataManager
        // If we have a reset token from deep link, skip to password reset step
        if let token = resetToken {
            self.resetToken = token
            self.currentStep = .resetPassword
        }
    }

    // MARK: - Public Methods

    /// Step 1: Request password reset code
    func requestPasswordReset() {
        if let error = ValidationRules.validateEmail(email) {
            errorMessage = error.errorDescription
            return
        }

        isLoading = true
        errorMessage = nil

        Task {
            do {
                let request = ForgotPasswordRequest(email: email)
                let result = try await APILayer.shared.forgotPassword(request: request)

                if result is ApiResultSuccess<ForgotPasswordResponse> {
                    self.isLoading = false
                    self.successMessage = "Check your email for a 6-digit verification code"

                    // Automatically move to next step after short delay
                    self.delayedTransitionTask?.cancel()
                    self.delayedTransitionTask = Task {
                        try? await Task.sleep(nanoseconds: 1_500_000_000)
                        guard !Task.isCancelled else { return }
                        self.successMessage = nil
                        self.currentStep = .verifyCode
                    }
                } else if let error = ApiResultBridge.error(from: result) {
                    self.isLoading = false
                    self.errorMessage = ErrorMessageParser.parse(error.message)
                } else {
                    self.isLoading = false
                    self.errorMessage = "Failed to request password reset"
                }
            } catch {
                self.isLoading = false
                self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
            }
        }
    }

    /// Step 2: Verify reset code
    func verifyResetCode() {
        if let error = ValidationRules.validateCode(code, expectedLength: 6) {
            errorMessage = error.errorDescription
            return
        }

        isLoading = true
        errorMessage = nil

        Task {
            do {
                let request = VerifyResetCodeRequest(email: email, code: code)
                let result = try await APILayer.shared.verifyResetCode(request: request)

                if let success = result as? ApiResultSuccess<VerifyResetCodeResponse>, let response = success.data {
                    let token = response.resetToken
                    self.resetToken = token
                    self.isLoading = false
                    self.successMessage = "Code verified! Now set your new password"

                    // Automatically move to next step after short delay
                    self.delayedTransitionTask?.cancel()
                    self.delayedTransitionTask = Task {
                        try? await Task.sleep(nanoseconds: 1_500_000_000)
                        guard !Task.isCancelled else { return }
                        self.successMessage = nil
                        self.currentStep = .resetPassword
                    }
                } else if let error = ApiResultBridge.error(from: result) {
                    self.isLoading = false
                    self.handleVerifyError(ErrorMessageParser.parse(error.message))
                } else {
                    self.isLoading = false
                    self.errorMessage = "Failed to verify code"
                }
            } catch {
                self.isLoading = false
                self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
            }
        }
    }

    /// Step 3: Reset password
    func resetPassword() {
        if let error = ValidationRules.validatePassword(newPassword) {
            errorMessage = error.errorDescription
            return
        }

        if let error = ValidationRules.validatePasswordStrength(newPassword) {
            errorMessage = error.errorDescription
            return
        }

        if let error = ValidationRules.validatePasswordMatch(newPassword, confirmPassword) {
            errorMessage = error.errorDescription
            return
        }

        guard let token = resetToken else {
            errorMessage = "Invalid reset token. Please start over."
            return
        }

        isLoading = true
        errorMessage = nil

        Task {
            do {
                let request = ResetPasswordRequest(
                    resetToken: token,
                    newPassword: newPassword
                )
                let result = try await APILayer.shared.resetPassword(request: request)

                if result is ApiResultSuccess<ResetPasswordResponse> {
                    // Password reset successful - now auto-login
                    self.successMessage = "Password reset successfully! Logging you in..."
                    self.currentStep = .loggingIn
                    await self.autoLogin()
                } else if let error = ApiResultBridge.error(from: result) {
                    self.isLoading = false
                    self.errorMessage = ErrorMessageParser.parse(error.message)
                } else {
                    self.isLoading = false
                    self.errorMessage = "Failed to reset password"
                }
            } catch {
                self.isLoading = false
                self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
            }
        }
    }

    /// Auto-login after successful password reset
    private func autoLogin() async {
        // Use the email from the reset flow as the username
        let username = email

        guard !username.isEmpty else {
            // If we don't have the email (e.g., deep link flow), fall back to manual login
            self.isLoading = false
            self.successMessage = "Password reset successfully! You can now log in with your new password."
            self.currentStep = .success
            return
        }

        do {
            let loginResult = try await APILayer.shared.login(
                request: LoginRequest(username: username, password: newPassword)
            )

            if let success = loginResult as? ApiResultSuccess<AuthResponse>,
               let response = success.data {
                let isVerified = response.user.verified

                // Lookups are already initialized by APILayer.login() internally
                // (see APILayer.kt line 1205) — no need to call again here

                self.isLoading = false

                // Call the login success callback
                self.onLoginSuccess?(isVerified)
            } else if let error = ApiResultBridge.error(from: loginResult) {
                // Auto-login failed, fall back to manual login
                #if DEBUG
                print("Auto-login failed: \(error.message)")
                #endif
                self.isLoading = false
                self.successMessage = "Password reset successfully! You can now log in with your new password."
                self.currentStep = .success
            } else {
                self.isLoading = false
                self.successMessage = "Password reset successfully! You can now log in with your new password."
                self.currentStep = .success
            }
        } catch {
            // Auto-login failed, fall back to manual login
            #if DEBUG
            print("Auto-login error: \(error.localizedDescription)")
            #endif
            self.isLoading = false
            self.successMessage = "Password reset successfully! You can now log in with your new password."
            self.currentStep = .success
        }
    }

    /// Navigate to next step
    func moveToNextStep() {
        switch currentStep {
        case .requestCode:
            currentStep = .verifyCode
        case .verifyCode:
            currentStep = .resetPassword
        case .resetPassword:
            currentStep = .loggingIn
        case .loggingIn:
            currentStep = .success
        case .success:
            break
        }
    }

    /// Navigate to previous step
    func moveToPreviousStep() {
        switch currentStep {
        case .requestCode:
            break
        case .verifyCode:
            currentStep = .requestCode
        case .resetPassword:
            currentStep = .verifyCode
        case .loggingIn, .success:
            break
        }
    }

    /// Reset all state
    func reset() {
        delayedTransitionTask?.cancel()
        delayedTransitionTask = nil
        email = ""
        code = ""
        newPassword = ""
        confirmPassword = ""
        resetToken = nil
        errorMessage = nil
        successMessage = nil
        currentStep = .requestCode
        isLoading = false
    }

    deinit {
        delayedTransitionTask?.cancel()
    }

    func clearError() {
        errorMessage = nil
    }

    func clearSuccess() {
        successMessage = nil
    }

    // MARK: - Private Methods

    private func handleVerifyError(_ message: String) {
        // Handle specific error cases
        let normalized = message.lowercased()

        if normalized.contains("expired") {
            errorMessage = "Reset code has expired. Please request a new one."
        } else if normalized.contains("attempts") {
            errorMessage = "Too many failed attempts. Please request a new reset code."
        } else if normalized.contains("invalid") && normalized.contains("token") {
            errorMessage = "Invalid or expired reset token. Please start over."
        } else {
            errorMessage = message
        }
    }
}
