package id.iiyh.inatrading.feature.profile.presentation

import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import id.iiyh.inatrading.feature.auth.domain.repository.AuthRepository
import id.iiyh.inatrading.feature.profile.data.model.CityItem
import id.iiyh.inatrading.feature.profile.data.model.CreateShippingAddressRequest
import id.iiyh.inatrading.feature.profile.data.model.ProvinceItem
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

data class EditShippingAddressUiState(
    val isLoading: Boolean = false,
    val isSaving: Boolean = false,
    val isDeleting: Boolean = false,
    val addressId: String = "",
    val label: String = "",
    val customLabel: String = "",
    val recipient: String = "",
    val phone: String = "",
    val countryKey: String = ADDRESS_COUNTRY_INDONESIA,
    val customCountry: String = "",
    val provinces: List<ProvinceItem> = emptyList(),
    val cities: List<CityItem> = emptyList(),
    val selectedProvinceId: String? = null,
    val selectedCityId: String? = null,
    val isLoadingProvinces: Boolean = false,
    val isLoadingCities: Boolean = false,
    val country: String = "",
    val province: String = "",
    val city: String = "",
    val postalCode: String = "",
    val address: String = "",
    val isPrimary: Boolean = false,
    val latitude: Double? = null,
    val longitude: Double? = null,
    val isResolvingLocation: Boolean = false,
    val errorMessage: String? = null,
    val infoMessage: String? = null,
    val saveSuccess: Boolean = false,
    val deleteSuccess: Boolean = false,
)

@HiltViewModel
class EditShippingAddressViewModel @Inject constructor(
    savedStateHandle: SavedStateHandle,
    private val authRepository: AuthRepository,
) : ViewModel() {

    private val addressId: String = savedStateHandle["addressId"] ?: ""

    private val _uiState = MutableStateFlow(EditShippingAddressUiState(addressId = addressId))
    val uiState: StateFlow<EditShippingAddressUiState> = _uiState.asStateFlow()

    init {
        loadAddress()
    }

    fun loadAddress() {
        if (addressId.isBlank()) {
            _uiState.update { it.copy(errorMessage = "Alamat tidak ditemukan.") }
            return
        }
        viewModelScope.launch {
            _uiState.update { it.copy(isLoading = true, errorMessage = null) }
            authRepository.getAddresses()
                .onSuccess { addresses ->
                    val address = addresses.firstOrNull { it.id == addressId }
                    if (address == null) {
                        _uiState.update {
                            it.copy(
                                isLoading = false,
                                errorMessage = "Alamat tidak ditemukan.",
                            )
                        }
                    } else {
                        val resolvedLabel = address.label.orEmpty()
                        val isPreset = isPresetLabel(resolvedLabel)
                        val isIndonesia = address.country.orEmpty().equals("indonesia", true)
                        _uiState.update {
                            it.copy(
                                isLoading = false,
                                label = if (isPreset) resolvedLabel else CUSTOM_LABEL_KEY,
                                customLabel = if (isPreset) "" else resolvedLabel,
                                recipient = address.recipient.orEmpty(),
                                phone = address.mobile.orEmpty(),
                                countryKey = if (isIndonesia) ADDRESS_COUNTRY_INDONESIA else ADDRESS_COUNTRY_OTHER,
                                customCountry = if (isIndonesia) "" else address.country.orEmpty(),
                                country = address.country.orEmpty(),
                                province = address.province.orEmpty(),
                                city = address.city.orEmpty(),
                                postalCode = address.postalCode.orEmpty(),
                                address = address.address.orEmpty(),
                                isPrimary = address.isPrimary,
                                latitude = address.latitude,
                                longitude = address.longitude,
                            )
                        }
                        if (isIndonesia) {
                            loadProvinces(
                                initialProvinceName = address.province.orEmpty(),
                                initialCityName = address.city.orEmpty(),
                            )
                        }
                    }
                }
                .onFailure { error ->
                    _uiState.update {
                        it.copy(
                            isLoading = false,
                            errorMessage = error.message ?: "Gagal memuat alamat",
                        )
                    }
                }
        }
    }

    fun onLabelSelected(value: String) {
        _uiState.update { it.copy(label = value, customLabel = "") }
    }

    fun onCustomLabelSelected() {
        _uiState.update {
            it.copy(
                label = CUSTOM_LABEL_KEY,
                customLabel = it.customLabel,
            )
        }
    }

    fun onCustomLabelChange(value: String) {
        _uiState.update {
            it.copy(
                label = CUSTOM_LABEL_KEY,
                customLabel = value,
            )
        }
    }

    fun onRecipientChange(value: String) {
        _uiState.update { it.copy(recipient = value) }
    }

    fun onPhoneChange(value: String) {
        _uiState.update { it.copy(phone = value.filter(Char::isDigit)) }
    }

    fun onCountryChange(value: String) {
        _uiState.update { it.copy(country = value) }
    }

    fun onCountrySelected(value: String) {
        _uiState.update {
            it.copy(
                countryKey = value,
                customCountry = if (value == ADDRESS_COUNTRY_OTHER) it.customCountry else "",
                country = if (value == ADDRESS_COUNTRY_INDONESIA) "Indonesia" else it.country,
                province = "",
                city = "",
                selectedProvinceId = null,
                selectedCityId = null,
                cities = emptyList(),
            )
        }
        if (value == ADDRESS_COUNTRY_INDONESIA) {
            loadProvinces()
        }
    }

    fun onCustomCountryChange(value: String) {
        _uiState.update { it.copy(customCountry = value, country = value) }
    }

    fun onProvinceChange(value: String) {
        _uiState.update { it.copy(province = value) }
    }

    fun onProvinceSelected(id: String) {
        val province = _uiState.value.provinces.firstOrNull { it.id == id } ?: return
        _uiState.update {
            it.copy(
                selectedProvinceId = province.id,
                province = province.name.orEmpty(),
                selectedCityId = null,
                city = "",
                cities = emptyList(),
            )
        }
        province.id?.let { loadCities(it) }
    }

    fun onCityChange(value: String) {
        _uiState.update { it.copy(city = value) }
    }

    fun onCitySelected(id: String) {
        val city = _uiState.value.cities.firstOrNull { it.id == id } ?: return
        _uiState.update {
            it.copy(
                selectedCityId = city.id,
                city = city.name.orEmpty(),
            )
        }
    }

    fun onPostalCodeChange(value: String) {
        _uiState.update { it.copy(postalCode = value.filter(Char::isDigit)) }
    }

    fun onAddressChange(value: String) {
        _uiState.update { it.copy(address = value) }
    }

    fun onPrimaryChange(value: Boolean) {
        _uiState.update { it.copy(isPrimary = value) }
    }

    fun onLocationCaptured(latitude: Double, longitude: Double) {
        _uiState.update {
            it.copy(
                latitude = latitude,
                longitude = longitude,
                isResolvingLocation = false,
                infoMessage = "Lokasi saat ini berhasil digunakan.",
            )
        }
    }

    fun onLocationError(message: String) {
        _uiState.update { it.copy(isResolvingLocation = false, infoMessage = message) }
    }

    fun onLocationRequestStarted() {
        _uiState.update {
            it.copy(
                isResolvingLocation = true,
                infoMessage = "Mengambil koordinat lokasi saat ini...",
            )
        }
    }

    fun onSaveClick() {
        val state = _uiState.value
        if (state.recipient.isBlank()) {
            _uiState.update { it.copy(infoMessage = "Nama penerima wajib diisi.") }
            return
        }
        if (state.phone.isBlank()) {
            _uiState.update { it.copy(infoMessage = "Nomor telepon wajib diisi.") }
            return
        }
        if (state.province.isBlank()) {
            _uiState.update { it.copy(infoMessage = "Provinsi wajib diisi.") }
            return
        }
        if (state.city.isBlank()) {
            _uiState.update { it.copy(infoMessage = "Kota wajib diisi.") }
            return
        }
        if (state.postalCode.isBlank()) {
            _uiState.update { it.copy(infoMessage = "Kode pos wajib diisi.") }
            return
        }
        if (state.address.isBlank()) {
            _uiState.update { it.copy(infoMessage = "Detail alamat wajib diisi.") }
            return
        }
        if (state.label == CUSTOM_LABEL_KEY && state.customLabel.isBlank()) {
            _uiState.update { it.copy(infoMessage = "Label alamat wajib diisi.") }
            return
        }
        if (state.resolvedCountry().isBlank()) {
            _uiState.update { it.copy(infoMessage = "Negara wajib dipilih.") }
            return
        }
        if (state.countryKey == ADDRESS_COUNTRY_INDONESIA && state.selectedProvinceId == null) {
            _uiState.update { it.copy(infoMessage = "Provinsi wajib dipilih.") }
            return
        }
        if (state.countryKey == ADDRESS_COUNTRY_INDONESIA && state.selectedCityId == null) {
            _uiState.update { it.copy(infoMessage = "Kota/Kabupaten wajib dipilih.") }
            return
        }
        if (state.isResolvingLocation) {
            _uiState.update { it.copy(infoMessage = "Tunggu sampai koordinat lokasi selesai diambil.") }
            return
        }

        viewModelScope.launch {
            _uiState.update { it.copy(isSaving = true, infoMessage = null) }
            authRepository.updateAddress(
                addressId = state.addressId,
                request = CreateShippingAddressRequest(
                    label = state.submittedLabel(),
                    recipient = state.recipient.trim(),
                    mobile = normalizePhone(state.phone),
                    address = state.address.trim(),
                    country = state.resolvedCountry(),
                    province = state.province.trim(),
                    city = state.city.trim(),
                    postalCode = state.postalCode.trim(),
                    isPrimary = state.isPrimary,
                    latitude = state.latitude,
                    longitude = state.longitude,
                ),
            ).onSuccess {
                _uiState.update {
                    it.copy(
                        isSaving = false,
                        saveSuccess = true,
                        infoMessage = "Alamat berhasil diperbarui.",
                    )
                }
            }.onFailure { error ->
                _uiState.update {
                    it.copy(
                        isSaving = false,
                        infoMessage = error.message ?: "Gagal memperbarui alamat",
                    )
                }
            }
        }
    }

    fun onDeleteClick() {
        val state = _uiState.value
        if (state.addressId.isBlank()) {
            _uiState.update { it.copy(infoMessage = "Alamat tidak ditemukan.") }
            return
        }

        viewModelScope.launch {
            _uiState.update { it.copy(isDeleting = true, infoMessage = null) }
            authRepository.deleteAddress(state.addressId)
                .onSuccess {
                    _uiState.update {
                        it.copy(
                            isDeleting = false,
                            deleteSuccess = true,
                            infoMessage = "Alamat berhasil dihapus.",
                        )
                    }
                }
                .onFailure { error ->
                    _uiState.update {
                        it.copy(
                            isDeleting = false,
                            infoMessage = error.message ?: "Gagal menghapus alamat",
                        )
                    }
                }
        }
    }

    fun consumeInfoMessage() {
        _uiState.update { it.copy(infoMessage = null) }
    }

    fun consumeSaveSuccess() {
        _uiState.update { it.copy(saveSuccess = false) }
    }

    fun consumeDeleteSuccess() {
        _uiState.update { it.copy(deleteSuccess = false) }
    }

    private fun loadProvinces(
        initialProvinceName: String? = null,
        initialCityName: String? = null,
    ) {
        viewModelScope.launch {
            _uiState.update { it.copy(isLoadingProvinces = true) }
            authRepository.getProvinces()
                .onSuccess { provinces ->
                    val sorted = provinces.sortedBy { item -> item.name.orEmpty() }
                    val matchedProvince = initialProvinceName?.let { provinceName ->
                        sorted.firstOrNull { it.name.orEmpty().equals(provinceName, true) }
                    }
                    _uiState.update {
                        it.copy(
                            isLoadingProvinces = false,
                            provinces = sorted,
                            selectedProvinceId = matchedProvince?.id ?: it.selectedProvinceId,
                            province = matchedProvince?.name.orEmpty().ifBlank { it.province },
                        )
                    }
                    matchedProvince?.id?.let { provinceId ->
                        loadCities(provinceId, initialCityName)
                    }
                }
                .onFailure { error ->
                    _uiState.update {
                        it.copy(
                            isLoadingProvinces = false,
                            infoMessage = error.message ?: "Gagal memuat provinsi",
                        )
                    }
                }
        }
    }

    private fun loadCities(
        provinceId: String,
        initialCityName: String? = null,
    ) {
        viewModelScope.launch {
            _uiState.update { it.copy(isLoadingCities = true) }
            authRepository.getCities(provinceId)
                .onSuccess { cities ->
                    val sorted = cities.sortedBy { item -> item.name.orEmpty() }
                    val matchedCity = initialCityName?.let { cityName ->
                        sorted.firstOrNull { it.name.orEmpty().equals(cityName, true) }
                    }
                    _uiState.update {
                        it.copy(
                            isLoadingCities = false,
                            cities = sorted,
                            selectedCityId = matchedCity?.id ?: it.selectedCityId,
                            city = matchedCity?.name.orEmpty().ifBlank { it.city },
                        )
                    }
                }
                .onFailure { error ->
                    _uiState.update {
                        it.copy(
                            isLoadingCities = false,
                            infoMessage = error.message ?: "Gagal memuat kota",
                        )
                    }
                }
        }
    }

    private fun normalizePhone(raw: String): String {
        val digits = raw.filter(Char::isDigit)
        if (digits.startsWith("0")) return digits
        if (digits.startsWith("62")) return "0${digits.removePrefix("62")}"
        return "0$digits"
    }

    private fun EditShippingAddressUiState.submittedLabel(): String {
        return if (label == CUSTOM_LABEL_KEY) customLabel.trim() else label.ifBlank { "rumah" }
    }

    private fun EditShippingAddressUiState.resolvedCountry(): String {
        return if (countryKey == ADDRESS_COUNTRY_OTHER) customCountry.trim() else "Indonesia"
    }

    private fun isPresetLabel(value: String): Boolean {
        return value.equals("rumah", true) ||
            value.equals("home", true) ||
            value.equals("kantor", true) ||
            value.equals("office", true) ||
            value.equals("gudang", true) ||
            value.equals("warehouse", true)
    }

    companion object {
        const val CUSTOM_LABEL_KEY = "__custom__"
    }
}
