import Foundation
import ComposeApp

/// Manages contractor export and import via .honeydue files.
/// Singleton that handles file creation for sharing and parsing for import.
@MainActor
class ContractorSharingManager: ObservableObject {

    // MARK: - Singleton

    static let shared = ContractorSharingManager()

    // MARK: - Published Properties

    @Published var isImporting: Bool = false
    @Published var importError: String?
    @Published var importSuccess: Bool = false
    @Published var importedContractorName: String?

    // MARK: - Private Properties

    private let jsonDecoder = JSONDecoder()

    private init() {}

    // MARK: - Export

    /// Creates a shareable .honeydue file for a contractor.
    /// - Parameter contractor: The contractor to export
    /// - Returns: URL to the temporary file, or nil if creation failed
    func createShareableFile(contractor: Contractor) -> URL? {
        // Get current username for export metadata
        let currentUsername = DataManagerObservable.shared.currentUser?.username ?? "Unknown"

        let jsonContent = HoneyDueShareCodec.shared.encodeContractorPackage(
            contractor: contractor,
            exportedBy: currentUsername
        )

        guard let jsonData = jsonContent.data(using: .utf8) else {
            print("ContractorSharingManager: Failed to encode contractor package as UTF-8")
            return nil
        }

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

        do {
            try jsonData.write(to: tempURL)
            // Track contractor shared event
            AnalyticsManager.shared.track(.contractorShared)
            return tempURL
        } catch {
            print("ContractorSharingManager: Failed to write .honeydue file: \(error)")
            return nil
        }
    }

    // MARK: - Import

    /// Imports a contractor from a .honeydue file URL.
    /// - Parameters:
    ///   - url: The URL to the .honeydue file
    ///   - completion: Called with true on success, false on failure
    func importContractor(from url: URL, completion: @escaping (Bool) -> Void) {
        isImporting = true
        importError = nil

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

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

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

            // Resolve specialty names to IDs
            let specialties = DataManagerObservable.shared.contractorSpecialties
            let specialtyIds = exportData.resolveSpecialtyIds(availableSpecialties: specialties)

            // Create the request
            let createRequest = exportData.toCreateRequest(specialtyIds: specialtyIds)

            // Call API to create contractor
            Task {
                do {
                    let result = try await APILayer.shared.createContractor(request: createRequest)

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

    /// Resets the import state after showing success/error feedback
    func resetImportState() {
        importError = nil
        importSuccess = false
        importedContractorName = nil
    }
}

// MARK: - Swift Codable Structure

/// Swift-native Codable structure for .honeydue file format.
/// This mirrors the Kotlin SharedContractor model for JSON serialization.
struct SharedContractorExport: Codable {
    let version: Int
    let name: String
    let company: String?
    let phone: String?
    let email: String?
    let website: String?
    let notes: String?
    let streetAddress: String?
    let city: String?
    let stateProvince: String?
    let postalCode: String?
    let specialtyNames: [String]
    let rating: Double?
    let isFavorite: Bool
    let exportedAt: String?
    let exportedBy: String?

    enum CodingKeys: String, CodingKey {
        case version
        case name
        case company
        case phone
        case email
        case website
        case notes
        case streetAddress = "street_address"
        case city
        case stateProvince = "state_province"
        case postalCode = "postal_code"
        case specialtyNames = "specialty_names"
        case rating
        case isFavorite = "is_favorite"
        case exportedAt = "exported_at"
        case exportedBy = "exported_by"
    }

    /// Initialize from Kotlin SharedContractor
    init(from sharedContractor: SharedContractor) {
        self.version = Int(sharedContractor.version)
        self.name = sharedContractor.name
        self.company = sharedContractor.company
        self.phone = sharedContractor.phone
        self.email = sharedContractor.email
        self.website = sharedContractor.website
        self.notes = sharedContractor.notes
        self.streetAddress = sharedContractor.streetAddress
        self.city = sharedContractor.city
        self.stateProvince = sharedContractor.stateProvince
        self.postalCode = sharedContractor.postalCode
        self.specialtyNames = sharedContractor.specialtyNames
        self.rating = sharedContractor.rating?.doubleValue
        self.isFavorite = sharedContractor.isFavorite
        self.exportedAt = sharedContractor.exportedAt
        self.exportedBy = sharedContractor.exportedBy
    }

    /// Resolve specialty names to IDs using available specialties
    func resolveSpecialtyIds(availableSpecialties: [ContractorSpecialty]) -> [Int32] {
        return specialtyNames.compactMap { name in
            availableSpecialties.first { specialty in
                specialty.name.lowercased() == name.lowercased()
            }?.id
        }
    }

    /// Convert to ContractorCreateRequest for API call
    func toCreateRequest(specialtyIds: [Int32]) -> ContractorCreateRequest {
        let residenceIdValue: KotlinInt? = nil
        let ratingValue: KotlinDouble? = rating.map { KotlinDouble(double: $0) }
        let specialtyIdsValue: [KotlinInt]? = specialtyIds.isEmpty ? nil : specialtyIds.map { KotlinInt(int: $0) }

        return ContractorCreateRequest(
            name: name,
            residenceId: residenceIdValue,
            company: company,
            phone: phone,
            email: email,
            website: website,
            streetAddress: streetAddress,
            city: city,
            stateProvince: stateProvince,
            postalCode: postalCode,
            rating: ratingValue,
            isFavorite: isFavorite,
            notes: notes,
            specialtyIds: specialtyIdsValue
        )
    }
}
