package com.tt.honeyDue.models

import kotlin.time.Clock
import kotlin.time.ExperimentalTime
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonPrimitive

/**
 * Package type identifiers for .honeydue files
 */
object HoneyDuePackageType {
    const val CONTRACTOR = "contractor"
    const val RESIDENCE = "residence"
}

/**
 * Data model for .honeydue file format used to share contractors between users.
 * Contains only the data needed to recreate a contractor, without server-specific IDs.
 */
@Serializable
data class SharedContractor(
    /** File format version for future compatibility */
    val version: Int = 1,

    /** Package type discriminator */
    val type: String = HoneyDuePackageType.CONTRACTOR,

    val name: String,
    val company: String? = null,
    val phone: String? = null,
    val email: String? = null,
    val website: String? = null,
    val notes: String? = null,

    @SerialName("street_address")
    val streetAddress: String? = null,
    val city: String? = null,
    @SerialName("state_province")
    val stateProvince: String? = null,
    @SerialName("postal_code")
    val postalCode: String? = null,

    /** Specialty names (not IDs) for cross-account compatibility */
    @SerialName("specialty_names")
    val specialtyNames: List<String> = emptyList(),

    val rating: Double? = null,
    @SerialName("is_favorite")
    val isFavorite: Boolean = false,

    /** ISO8601 timestamp when the contractor was exported */
    @SerialName("exported_at")
    val exportedAt: String? = null,

    /** Username of the person who exported the contractor */
    @SerialName("exported_by")
    val exportedBy: String? = null
)

/**
 * Data model for .honeydue file format used to share residences between users.
 * Contains the share code needed to join the residence.
 */
@Serializable
data class SharedResidence(
    /** File format version for future compatibility */
    val version: Int = 1,

    /** Package type discriminator */
    val type: String = HoneyDuePackageType.RESIDENCE,

    /** The share code for joining the residence */
    @SerialName("share_code")
    val shareCode: String,

    /** Name of the residence being shared */
    @SerialName("residence_name")
    val residenceName: String,

    /** Email of the person sharing the residence */
    @SerialName("shared_by")
    val sharedBy: String? = null,

    /** ISO8601 timestamp when the code expires */
    @SerialName("expires_at")
    val expiresAt: String? = null,

    /** ISO8601 timestamp when the package was created */
    @SerialName("exported_at")
    val exportedAt: String? = null,

    /** Username of the person who created the package */
    @SerialName("exported_by")
    val exportedBy: String? = null
)

/**
 * Detect the type of a .honeydue package from its JSON content.
 * Returns null if the type cannot be determined.
 */
fun detectHoneyDuePackageType(jsonContent: String): String? {
    return try {
        val json = Json { ignoreUnknownKeys = true }
        val jsonObject = json.decodeFromString<JsonObject>(jsonContent)
        jsonObject["type"]?.jsonPrimitive?.content ?: HoneyDuePackageType.CONTRACTOR // Default for backward compatibility
    } catch (e: Exception) {
        null
    }
}

/**
 * Convert a full Contractor to SharedContractor for export.
 */
@OptIn(ExperimentalTime::class)
fun Contractor.toSharedContractor(exportedBy: String? = null): SharedContractor {
    return SharedContractor(
        version = 1,
        type = HoneyDuePackageType.CONTRACTOR,
        name = name,
        company = company,
        phone = phone,
        email = email,
        website = website,
        notes = notes,
        streetAddress = streetAddress,
        city = city,
        stateProvince = stateProvince,
        postalCode = postalCode,
        specialtyNames = specialties.map { it.name },
        rating = rating,
        isFavorite = isFavorite,
        exportedAt = Clock.System.now().toString(),
        exportedBy = exportedBy
    )
}

/**
 * Convert SharedContractor to ContractorCreateRequest for import.
 * @param specialtyIds The resolved specialty IDs from the importing account's lookup data
 */
fun SharedContractor.toCreateRequest(specialtyIds: List<Int>): ContractorCreateRequest {
    return ContractorCreateRequest(
        name = name,
        residenceId = null, // Imported contractors have no residence association
        company = company,
        phone = phone,
        email = email,
        website = website,
        streetAddress = streetAddress,
        city = city,
        stateProvince = stateProvince,
        postalCode = postalCode,
        rating = rating,
        isFavorite = isFavorite,
        notes = notes,
        specialtyIds = specialtyIds.ifEmpty { null }
    )
}

/**
 * Resolve specialty names to IDs using the available specialties in the importing account.
 * Case-insensitive matching.
 */
fun SharedContractor.resolveSpecialtyIds(availableSpecialties: List<ContractorSpecialty>): List<Int> {
    return specialtyNames.mapNotNull { name ->
        availableSpecialties.find { specialty ->
            specialty.name.equals(name, ignoreCase = true)
        }?.id
    }
}
