import Foundation
import SwiftUI

@MainActor @Observable
final class AuthManager {
    var isAuthenticated = false
    var isCheckingAuth = true
    var user: AuthUser?
    var loginError: String?

    private let api = APIClient.shared

    struct LoginRequest: Encodable {
        let username: String
        let password: String
    }

    struct LoginResponse: Decodable {
        let success: Bool?
        let user: AuthUser?
        let error: String?
    }

    struct AuthResponse: Decodable {
        let authenticated: Bool?
        let user: AuthUser?
    }

    struct AuthUser: Decodable {
        let id: IntOrString
        let username: String?
        let displayName: String?

        enum CodingKeys: String, CodingKey {
            case id, username
            case displayName = "display_name"
        }
    }

    // Gateway returns id as Int, handle both Int and String
    struct IntOrString: Decodable {
        let value: String
        init(from decoder: Decoder) throws {
            let container = try decoder.singleValueContainer()
            if let intVal = try? container.decode(Int.self) {
                value = String(intVal)
            } else {
                value = try container.decode(String.self)
            }
        }
    }

    func checkAuth() async {
        isCheckingAuth = true
        defer { isCheckingAuth = false }

        // Check if we had a previous session
        guard UserDefaults.standard.bool(forKey: "is_logged_in") else {
            isAuthenticated = false
            return
        }

        do {
            let response: AuthResponse = try await api.get("/api/auth/me")
            if response.authenticated == true {
                isAuthenticated = true
                user = response.user
            } else {
                isAuthenticated = false
                UserDefaults.standard.set(false, forKey: "is_logged_in")
            }
        } catch {
            isAuthenticated = false
            UserDefaults.standard.set(false, forKey: "is_logged_in")
        }
    }

    func login(username: String, password: String) async {
        loginError = nil

        do {
            let body = LoginRequest(username: username, password: password)
            let loginResp: LoginResponse = try await api.post("/api/auth/login", body: body)

            if loginResp.success == true {
                user = loginResp.user
                isAuthenticated = true
                UserDefaults.standard.set(true, forKey: "is_logged_in")
            } else {
                loginError = loginResp.error ?? "Authentication failed"
            }
        } catch let error as APIError {
            switch error {
            case .httpError(let code, _):
                if code == 401 {
                    loginError = "Invalid username or password"
                } else {
                    loginError = "Server error (\(code))"
                }
            default:
                loginError = error.localizedDescription
            }
        } catch {
            loginError = error.localizedDescription
        }
    }

    func logout() {
        api.clearCookies()
        isAuthenticated = false
        user = nil
        UserDefaults.standard.set(false, forKey: "is_logged_in")
    }
}
