import Foundation
import ComposeApp

/// Manages residence share package creation and import via .honeydue files.
/// For residences, the share code is generated server-side (unlike contractors which are exported client-side).
@MainActor
class ResidenceSharingManager: ObservableObject {

    // MARK: - Singleton

    static let shared = ResidenceSharingManager()

    // MARK: - Published Properties

    /// True while generating a share package from the server
    @Published var isGeneratingPackage: Bool = false

    /// True while importing a residence from a share package
    @Published var isImporting: Bool = false

    /// Error message if generation or import fails
    @Published var errorMessage: String?

    /// True after successful import
    @Published var importSuccess: Bool = false

    /// Name of the imported residence
    @Published var importedResidenceName: String?

    // MARK: - Private Properties

    private let jsonDecoder = JSONDecoder()

    private init() {}

    // MARK: - Export (Share)

    /// Creates a shareable .honeydue file for a residence.
    /// This calls the backend to generate a one-time share code, then packages it.
    /// - Parameter residence: The residence to share
    /// - Returns: URL to the temporary file, or nil if creation failed
    func createShareableFile(residence: ResidenceResponse) async -> URL? {
        isGeneratingPackage = true
        errorMessage = nil

        defer { isGeneratingPackage = false }

        // Call API to generate share package
        let result: Any
        do {
            result = try await APILayer.shared.generateSharePackage(residenceId: residence.id)
        } catch {
            errorMessage = "Failed to generate share code: \(error.localizedDescription)"
            return nil
        }

        guard let success = result as? ApiResultSuccess<SharedResidence>,
              let sharedResidence = success.data else {
            if let error = ApiResultBridge.error(from: result) {
                errorMessage = ErrorMessageParser.parse(error.message)
            } else {
                errorMessage = "Failed to generate share code"
            }
            return nil
        }

        let jsonContent = HoneyDueShareCodec.shared.encodeSharedResidence(sharedResidence: sharedResidence)
        guard let jsonData = jsonContent.data(using: .utf8) else {
            #if DEBUG
            print("ResidenceSharingManager: Failed to encode residence package as UTF-8")
            #endif
            errorMessage = "Failed to create share file"
            return nil
        }

        let fileName = HoneyDueShareCodec.shared.safeShareFileName(displayName: residence.name)
        let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent(fileName)

        do {
            try jsonData.write(to: tempURL)
            // Track residence shared event
            AnalyticsManager.shared.track(.residenceShared(method: "file"))
            return tempURL
        } catch {
            #if DEBUG
            print("ResidenceSharingManager: Failed to write .honeydue file: \(error)")
            #endif
            errorMessage = "Failed to save share file"
            return nil
        }
    }

    // MARK: - Import

    /// Imports a residence share from a .honeydue file URL.
    /// This validates the share code with the server and adds the user to the residence.
    /// - Parameters:
    ///   - url: The URL to the .honeydue file
    ///   - completion: Called with true on success, false on failure
    func importResidence(from url: URL, completion: @escaping (Bool) -> Void) {
        isImporting = true
        errorMessage = nil

        // Verify user is authenticated
        guard TokenStorage.shared.getToken() != nil else {
            errorMessage = "You must be logged in to join a residence"
            isImporting = false
            completion(false)
            return
        }

        // Start accessing security-scoped resource if needed
        let accessing = url.startAccessingSecurityScopedResource()
        defer {
            if accessing {
                url.stopAccessingSecurityScopedResource()
            }
        }

        do {
            let data = try Data(contentsOf: url)
            let exportData = try jsonDecoder.decode(SharedResidenceExport.self, from: data)

            // Use the share code to join the residence
            Task {
                do {
                    let result = try await APILayer.shared.joinWithCode(code: exportData.shareCode)

                    if let success = result as? ApiResultSuccess<JoinResidenceResponse>,
                       let joinResponse = success.data {
                        self.importedResidenceName = joinResponse.residence.name
                        self.importSuccess = true
                        self.isImporting = false
                        completion(true)
                    } else if let error = ApiResultBridge.error(from: result) {
                        self.errorMessage = ErrorMessageParser.parse(error.message)
                        self.isImporting = false
                        completion(false)
                    } else {
                        self.errorMessage = "Unknown error occurred"
                        self.isImporting = false
                        completion(false)
                    }
                } catch {
                    self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
                    self.isImporting = false
                    completion(false)
                }
            }
        } catch {
            errorMessage = "Failed to read residence share file: \(error.localizedDescription)"
            isImporting = false
            completion(false)
        }
    }

    /// Resets the import state after showing success/error feedback
    func resetState() {
        errorMessage = nil
        importSuccess = false
        importedResidenceName = nil
    }
}

// MARK: - Swift Codable Structure

/// Swift-native Codable structure for .honeydue residence share format.
/// This mirrors the Kotlin SharedResidence model for JSON serialization.
struct SharedResidenceExport: Codable {
    let version: Int
    let type: String
    let shareCode: String
    let residenceName: String
    let sharedBy: String?
    let expiresAt: String?
    let exportedAt: String?
    let exportedBy: String?

    enum CodingKeys: String, CodingKey {
        case version
        case type
        case shareCode = "share_code"
        case residenceName = "residence_name"
        case sharedBy = "shared_by"
        case expiresAt = "expires_at"
        case exportedAt = "exported_at"
        case exportedBy = "exported_by"
    }

    /// Initialize from Kotlin SharedResidence
    init(from sharedResidence: SharedResidence) {
        self.version = Int(sharedResidence.version)
        self.type = sharedResidence.type
        self.shareCode = sharedResidence.shareCode
        self.residenceName = sharedResidence.residenceName
        self.sharedBy = sharedResidence.sharedBy
        self.expiresAt = sharedResidence.expiresAt
        self.exportedAt = sharedResidence.exportedAt
        self.exportedBy = sharedResidence.exportedBy
    }
}
