package com.tt.honeyDue.ui.screens.residence

import com.tt.honeyDue.models.ResidenceCreateRequest
import com.tt.honeyDue.models.ResidenceUpdateRequest

/**
 * Immutable snapshot of the create/edit-residence form field values.
 *
 * Mirrors the iOS `ResidenceFormView` state
 * (`iosApp/iosApp/ResidenceFormView.swift`) and its companion
 * `ResidenceFormState` (`iosApp/iosApp/Core/FormStates/ResidenceFormState.swift`).
 *
 * All fields except [name] are optional; string numeric fields stay as
 * strings here so the Compose layer can bind them directly to text inputs.
 * The `toCreateRequest` / `toUpdateRequest` builders perform the final
 * parse after validation.
 */
data class ResidenceFormFields(
    val name: String = "",
    val propertyTypeId: Int? = null,
    val streetAddress: String = "",
    val apartmentUnit: String = "",
    val city: String = "",
    val stateProvince: String = "",
    val postalCode: String = "",
    val country: String = "USA",
    val bedrooms: String = "",
    val bathrooms: String = "",
    val squareFootage: String = "",
    val lotSize: String = "",
    val yearBuilt: String = "",
    val description: String = "",
    val isPrimary: Boolean = false,
)

/**
 * Per-field error snapshot — one nullable string per validated field.
 * A `null` entry means "no error". Non-validated fields (address parts,
 * description, etc.) are not listed here because iOS has no rules for them.
 */
data class ResidenceFormErrors(
    val name: String? = null,
    val bedrooms: String? = null,
    val bathrooms: String? = null,
    val squareFootage: String? = null,
    val lotSize: String? = null,
    val yearBuilt: String? = null,
) {
    /** True when every entry is null — i.e. the form passes validation. */
    val isEmpty: Boolean
        get() = name == null &&
                bedrooms == null &&
                bathrooms == null &&
                squareFootage == null &&
                lotSize == null &&
                yearBuilt == null
}

/**
 * Mutable container that glues [ResidenceFormFields] to the pure
 * validators in [ResidenceFormValidation] and exposes typed request
 * builders. Mirrors the Stream W `TaskFormState` pattern.
 *
 * Deliberately not a Compose `State` — keep this plain so common tests
 * can exercise it without a UI runtime. The Compose call-site can wrap
 * the container in `remember { mutableStateOf(...) }` as needed.
 */
class ResidenceFormState(initial: ResidenceFormFields = ResidenceFormFields()) {

    var fields: ResidenceFormFields = initial
        private set

    /** Derived: recomputed from the current [fields] on every access. */
    val errors: ResidenceFormErrors
        get() = computeErrors(fields)

    /** Derived: `true` iff every validator returns `null`. */
    val isValid: Boolean
        get() = errors.isEmpty

    /** Replaces the current field snapshot. Errors/[isValid] update automatically. */
    fun update(f: ResidenceFormFields) {
        fields = f
    }

    /** Alias for `errors` — returned as an explicit snapshot for callers that prefer imperative style. */
    fun validate(): ResidenceFormErrors = errors

    /**
     * Builds a [ResidenceCreateRequest] from the current fields, or `null`
     * if the form does not validate. Blank optional strings are mapped to
     * `null` to match the iOS `submitForm()` mapping.
     */
    fun toCreateRequest(): ResidenceCreateRequest? {
        if (!isValid) return null
        val f = fields
        return ResidenceCreateRequest(
            name = f.name,
            propertyTypeId = f.propertyTypeId,
            streetAddress = f.streetAddress.blankToNull(),
            apartmentUnit = f.apartmentUnit.blankToNull(),
            city = f.city.blankToNull(),
            stateProvince = f.stateProvince.blankToNull(),
            postalCode = f.postalCode.blankToNull(),
            country = f.country.blankToNull(),
            bedrooms = f.bedrooms.blankToNull()?.toIntOrNull(),
            bathrooms = f.bathrooms.blankToNull()?.toDoubleOrNull(),
            squareFootage = f.squareFootage.blankToNull()?.toIntOrNull(),
            lotSize = f.lotSize.blankToNull()?.toDoubleOrNull(),
            yearBuilt = f.yearBuilt.blankToNull()?.toIntOrNull(),
            description = f.description.blankToNull(),
            isPrimary = f.isPrimary,
        )
    }

    /**
     * Builds a [ResidenceUpdateRequest] from the current fields, or `null`
     * if the form does not validate. Uses the same blank-to-null mapping
     * as create.
     */
    fun toUpdateRequest(residenceId: Int): ResidenceUpdateRequest? {
        if (!isValid) return null
        val f = fields
        return ResidenceUpdateRequest(
            name = f.name,
            propertyTypeId = f.propertyTypeId,
            streetAddress = f.streetAddress.blankToNull(),
            apartmentUnit = f.apartmentUnit.blankToNull(),
            city = f.city.blankToNull(),
            stateProvince = f.stateProvince.blankToNull(),
            postalCode = f.postalCode.blankToNull(),
            country = f.country.blankToNull(),
            bedrooms = f.bedrooms.blankToNull()?.toIntOrNull(),
            bathrooms = f.bathrooms.blankToNull()?.toDoubleOrNull(),
            squareFootage = f.squareFootage.blankToNull()?.toIntOrNull(),
            lotSize = f.lotSize.blankToNull()?.toDoubleOrNull(),
            yearBuilt = f.yearBuilt.blankToNull()?.toIntOrNull(),
            description = f.description.blankToNull(),
            isPrimary = f.isPrimary,
        )
    }

    /**
     * Overload for nav args typed as [Long]. Narrows to [Int] because the
     * wire model uses Int.
     */
    fun toUpdateRequest(residenceId: Long): ResidenceUpdateRequest? =
        toUpdateRequest(residenceId.toInt())

    private fun computeErrors(f: ResidenceFormFields): ResidenceFormErrors = ResidenceFormErrors(
        name = ResidenceFormValidation.validateName(f.name),
        bedrooms = ResidenceFormValidation.validateBedrooms(f.bedrooms),
        bathrooms = ResidenceFormValidation.validateBathrooms(f.bathrooms),
        squareFootage = ResidenceFormValidation.validateSquareFootage(f.squareFootage),
        lotSize = ResidenceFormValidation.validateLotSize(f.lotSize),
        yearBuilt = ResidenceFormValidation.validateYearBuilt(f.yearBuilt),
    )

    private fun String.blankToNull(): String? = ifBlank { null }
}
