<template>
    <form :class="{ submitted }" @submit.prevent="validate">
        <div class="flex items-center relative">
            <div class="flex flex-row absolute -left-[60px] ">
                <Icon @click="router.push('/admin/customer/customer-list')" name="gg:arrow-left-o" size="40" class="cursor-pointer text-primary-500"/>
            </div>
            <h1 class="text-3xl text-primary-500  font-bold uppercase">
                {{ customerId ? "Modification du client" : "Ajout d'un client" }}
            </h1>
        </div>

        <div class="flex flex-cols-3 justify-between mb-11 pt-7">
            <UiTextInput id="customer-name" v-model="form.name" label="Nom du client" :disabled="!auth.isAdmin" wrapper-class="w-[280px]" required/>
            <UiTextInput id="customer-phone" v-model="form.phone" label="Téléphone" :disabled="!auth.isAdmin" wrapper-class="w-[280px]" required/>
            <UiTextInput id="customer-email" v-model="form.email" label="Email" :disabled="!auth.isAdmin" wrapper-class="w-[280px]"/>
        </div>
        <div v-if="!customerId" class="flex flex-cols-3 justify-between mb-11">
            <UiTextInput id="address-street" v-model="addressForm.street" label="Rue" wrapper-class="w-[280px]" required />
            <UiTextInput id="address-street2" v-model="addressForm.street2" label="Complément" wrapper-class="w-[280px]" />
            <UiTextInput id="address-country" v-model="addressForm.countryCode" label="Pays (code)" wrapper-class="w-[280px]" />
        </div>
        <div v-if="!customerId" class="flex flex-cols-3 justify-between mb-11">
            <UiTextInput id="address-postalCode" v-model="addressForm.postalCode" label="Code postal" wrapper-class="w-[280px]" required />
            <UiSelect id="address-city" v-model="addressForm.city" label="Ville"
                      :options="communeOptions" :loading="isLoadingCities"
                      wrapper-class="w-[280px]" required />
            <div class="w-[280px]" />
        </div>

        <div class="flex items-center justify-center">
            <UiButton
                class="inline-flex mb-28 items-center justify-center text-xl min-w-[194px] text-white uppercase bg-primary-500 h-[50px] rounded hover:opacity-80 justify-self-end"
                type="submit"
                :disabled="isLoading || !auth.isAdmin"
                @click="submitted = true"
            >
                <Icon :name="customerId ? '' : 'mdi:plus'" size="28" />
                {{ customerId ? "Valider" : "Ajouter" }}
            </UiButton>
        </div>

        <template v-if="customerId">
        <div class="flex items-center justify-between mb-7">
            <h2 class="text-3xl text-primary-500 font-bold uppercase">Adresses du client</h2>
        </div>
        <div class="overflow-x-auto mb-11 text-primary-700">
            <table class="w-full border-collapse text-primary-700">
                <thead>
                <tr class="text-left border bg-slate-100 border-gray-200">
                    <th class="py-3 px-4 text-sm uppercase">Rue</th>
                    <th class="py-3 px-4 text-sm uppercase">Complément</th>
                    <th class="py-3 px-4 text-sm uppercase">Code postal</th>
                    <th class="py-3 px-4 text-sm uppercase">Ville</th>
                    <th class="py-3 px-4 text-sm uppercase">Pays</th>
                </tr>
                </thead>
                <tbody>
                <template v-if="form.addresses.length === 0">
                    <tr>
                        <td colspan="5" class="py-4 text-slate-400">
                            Aucune adresse.
                        </td>
                    </tr>
                </template>
                <template v-else>
                    <tr
                        v-for="(address, index) in form.addresses"
                        :key="address.id ?? index"
                        class="border border-gray-100 hover:bg-slate-50"
                        :class="auth.isAdmin ? 'cursor-pointer' : 'cursor-not-allowed opacity-60'"
                        @click="goToEditAddress(address.id ?? null)"
                    >
                        <td class="py-3 px-4">{{ address.street || "—" }}</td>
                        <td class="py-3 px-4">{{ address.street2 || "—" }}</td>
                        <td class="py-3 px-4">{{ address.postalCode || "—" }}</td>
                        <td class="py-3 px-4">{{ address.city || "—" }}</td>
                        <td class="py-3 px-4">{{ address.countryCode || "—" }}</td>
                    </tr>
                </template>
                </tbody>
            </table>
        </div>
        <div class="flex justify-center items-center">
            <UiButton
                type="button"
                class="inline-flex items-center justify-center text-xl gap-2 text-white uppercase bg-primary-500 h-[50px] rounded hover:opacity-80 justify-self-end"
                :disabled="customerId === null || !auth.isAdmin"
                @click="goToAddAddress"
            >
                <Icon name="mdi:plus" size="28" />
                Ajouter
            </UiButton>
        </div>
        </template>
    </form>
</template>

<script setup lang="ts">
import {computed, reactive, ref, watch} from "vue"
import {createCustomer, getCustomer, updateCustomer} from "~/services/customer"
import type {CustomerData, CustomerFormData, CustomerPayload} from "~/services/dto/customer-data"
import {createAddress, type AddressPayload} from "~/services/address"
import {getCommunesByPostalCode, type CommuneData} from "~/services/geo"
import {useAuthStore} from "~/stores/auth"

const route = useRoute()
const router = useRouter()
const auth = useAuthStore()

const resolveId = (param: unknown) => {
    const idStr = Array.isArray(param) ? param[0] : param
    if (!idStr) return null
    const id = Number(idStr)
    return Number.isFinite(id) ? id : null
}
const customerId = computed(() => resolveId(route.params.id))
const isLoading = ref(false)
const submitted = ref(false)
const form = reactive<CustomerFormData>({
    name: "",
    phone: "",
    email: "",
    addresses: [],
})

// Address form (creation mode only)
const addressForm = reactive<AddressPayload>({
    street: "", street2: null, postalCode: "", city: "", countryCode: "FR",
})
const communes = ref<CommuneData[]>([])
const isLoadingCities = ref(false)
const communeOptions = computed(() => communes.value.map(c => ({ value: c.nom, label: c.nom })))

let debounceTimer: ReturnType<typeof setTimeout> | null = null
watch(() => addressForm.postalCode, (cp) => {
    if (debounceTimer) clearTimeout(debounceTimer)
    if (!cp || cp.length < 5) { communes.value = []; addressForm.city = ''; return }
    if (cp.length === 5) {
        debounceTimer = setTimeout(async () => {
            isLoadingCities.value = true
            try {
                communes.value = await getCommunesByPostalCode(cp)
                if (communes.value.length === 1) addressForm.city = communes.value[0].nom
                else addressForm.city = ''
            } finally { isLoadingCities.value = false }
        }, 300)
    }
})

const goToAddAddress = () => {
    if (customerId.value === null || !auth.isAdmin) return
    router.push({
        path: "/admin/customer/address",
        query: {
            customerId: String(customerId.value),
        },
    })
}

const goToEditAddress = (addressId: number | null) => {
    if (customerId.value === null || addressId === null || !auth.isAdmin) return
    router.push({
        path: "/admin/customer/address",
        query: {
            customerId: String(customerId.value),
            addressId: String(addressId),
        },
    })
}

const hydrateFromCustomer = (customer: CustomerData | null) => {
    if (!customer) return
    form.name = customer.name ?? ""
    form.phone = customer.phone ?? ""
    form.email = customer.email ?? ""
    if (!Array.isArray(customer.addresses) || customer.addresses.length === 0) {
        form.addresses = []
        return
    }
    if (typeof customer.addresses[0] === "string") {
        form.addresses = []
        return
    }

    form.addresses = customer.addresses.map((address) => ({
        id: address.id ?? null,
        street: address.street ?? "",
        street2: address.street2 ?? null,
        postalCode: address.postalCode ?? "",
        city: address.city ?? "",
        countryCode: address.countryCode ?? "",
    }))
}

watch(
    () => customerId.value,
    async (id) => {
        if (id === null) return
        isLoading.value = true
        try {
            const customer = await getCustomer(id)
            hydrateFromCustomer(customer)
        } finally {
            isLoading.value = false
        }
    },
    {immediate: true}
)

async function validate() {
    if (isLoading.value) return
    if (!auth.isAdmin) return
    isLoading.value = true

    try {
        const name = form.name.trim()
        const phone = form.phone?.trim() || null
        const email = form.email?.trim() || null

        const customerPayload: CustomerPayload = {
            name,
            phone,
            email,
        }
        let targetId: number | null = null

        if (customerId.value !== null) {
            await updateCustomer(customerId.value, customerPayload)
            targetId = customerId.value
        } else {
            const addressData = await createAddress({ ...addressForm })
            const addressIRI = `/api/addresses/${addressData.id}`
            const creationPayload = {
                ...customerPayload,
                addresses: [addressIRI],
                ...(auth.user?.id ? { createdBy: `/api/users/${auth.user.id}` } : {}),
            }
            const created = await createCustomer(creationPayload)
            targetId = created.id
        }

        if (targetId !== null) {
            await router.push(`/admin/customer/${targetId}`)
        }
    } finally {
        isLoading.value = false
    }
}
</script>
