"use client"

import { AlertTriangle, Plus, Save, Trash2 } from "lucide-react"
import { useFieldArray } from "react-hook-form"

import { Button } from "@/shared/components/ui/button"
import { Alert, AlertTitle } from "@/shared/components/ui/alert"
import { FieldGroup } from "@/shared/components/ui/field"
import {
    Rhform,
    RhfTextField,
    RhfTextareaField,
    RhfAsyncSelectField,
    RhfCheckboxField,
} from "@/shared/components/form"
import { ShopTypeInlineForm } from "@/modules/vehicles/inline-forms/shop-type-inline-form"
import { InventoryCategoryInlineForm } from "@/modules/services/inline-forms/inventory-category-inline-form"
import { UnitTypeInlineForm } from "@/modules/services/inline-forms/unit-type-inline-form"
import { DepartmentInlineForm } from "@/modules/services/inline-forms/department-inline-form"
import { toast } from "sonner"
import { useAuthApi } from "@/shared/useApi"
import { useResourceForm } from "@/shared/hooks/use-resource-form"
import { useFormMutation } from "@/shared/hooks/use-form-mutation"
import { toId } from "@/shared/lib/utils"

import { serviceGroupFormSchema, type ServiceGroupFormValues } from "./service-group.schema"
import { SERVICE_GROUP_ROUTES } from "@garage/api"

// ── Props ──

export type ServiceGroupFormProps = {
    resourceId?: string | null
    initialData?: unknown
    onSuccess?: () => void
}

// ── Default values ──

const DEFAULT_VALUES: ServiceGroupFormValues = {
    shop_type: null,
    inventory_category: null,
    unit_type: null,
    department: null,
    service_name: "",
    code: "",
    service_description: "",
    selling_price: undefined,
    selling_chart_of_account: "",
    show_as_lump_sum: false,
    mark_as_recommended: false,
    set_packaged_pricing: false,
    is_active: true,
    parts: [],
    services: [],
}

// ── Mapping helpers ──

const mapLookupOption = (item: any) => ({
    value: String(item.id),
    label: item.name ?? item.title ?? String(item.id),
})

const STORE_OBJECT = { getOptionValue: (o: any) => o, getOptionLabel: (o: any) => o.label }

const partLineToForm = (r: any) => ({
    id: r.id,
    part: r.part ? { value: String(r.part.id), label: r.part.title ?? r.part.name ?? `#${r.part.id}` } : null,
    quantity: r.quantity != null ? Number(r.quantity) : 1,
    rate: r.rate != null ? Number(r.rate) : 0,
})

const serviceLineToForm = (r: any) => ({
    id: r.id,
    service: r.service ? { value: String(r.service.id), label: r.service.title ?? r.service.name ?? `#${r.service.id}` } : null,
    rate: r.rate != null ? Number(r.rate) : 0,
    hours: r.hours != null ? Number(r.hours) : 0,
})

function mapToFormValues(data: unknown): ServiceGroupFormValues {
    const d = (data as any)?.data ?? data ?? {}

    return {
        shop_type: null,
        inventory_category: null,
        unit_type: null,
        department: null,
        service_name: d.service_name ?? d.name ?? "",
        code: d.code ?? "",
        service_description: d.service_description ?? "",
        selling_price: d.selling_price ?? undefined,
        selling_chart_of_account: d.selling_chart_of_account ?? "",
        show_as_lump_sum: d.show_as_lump_sum ?? false,
        mark_as_recommended: d.mark_as_recommended ?? false,
        set_packaged_pricing: d.set_packaged_pricing ?? false,
        is_active: d.is_active ?? true,
        parts: Array.isArray(d._parts) ? d._parts.map(partLineToForm) : [],
        services: Array.isArray(d._services) ? d._services.map(serviceLineToForm) : [],
    }
}

function mapCreatePayload(values: ServiceGroupFormValues) {
    return {
        service_name: values.service_name,
        shop_type_id: toId(values.shop_type),
        code: values.code || undefined,
        inventory_category_id: toId(values.inventory_category),
        unit_type_id: toId(values.unit_type),
        department_id: toId(values.department),
        service_description: values.service_description || undefined,
        show_as_lump_sum: values.show_as_lump_sum,
        mark_as_recommended: values.mark_as_recommended,
        set_packaged_pricing: values.set_packaged_pricing,
        selling_price: values.selling_price,
        selling_chart_of_account: values.selling_chart_of_account || undefined,
        is_active: values.is_active,
    }
}

function mapUpdatePayload(values: ServiceGroupFormValues) {
    return {
        service_name: values.service_name,
        selling_price: values.selling_price,
        is_active: values.is_active,
    }
}

// ── Component ──

export function ServiceGroupForm({ resourceId, initialData, onSuccess }: ServiceGroupFormProps) {
    const api = useAuthApi()

    const { form, isEditing } = useResourceForm<ServiceGroupFormValues, any>({
        schema: serviceGroupFormSchema,
        defaultValues: DEFAULT_VALUES,
        resourceId,
        initialData,
        queryKey: [SERVICE_GROUP_ROUTES.BY_ID, resourceId],
        // Fetch the group together with its existing parts/services so the
        // pickers can be pre-populated when editing.
        initialize: async (id) => {
            const [group, parts, services] = await Promise.all([
                api.serviceGroups.show(id),
                api.serviceGroupParts.list({ service_group_id: id } as any),
                api.serviceGroupServices.list({ service_group_id: id } as any),
            ])
            const g = (group as any)?.data ?? group ?? {}
            return {
                data: {
                    ...g,
                    _parts: (parts as any)?.data ?? [],
                    _services: (services as any)?.data ?? [],
                },
            }
        },
        mapToFormValues,
    })

    const partsArray = useFieldArray({ control: form.control, name: "parts" })
    const servicesArray = useFieldArray({ control: form.control, name: "services" })

    // Replace the package's parts/services on the server with the current form
    // rows: delete the existing rows, then recreate from the form. Mirrors the
    // "replace details" approach used elsewhere (e.g. payments).
    const syncIncludes = async (groupId: string | number, values: ServiceGroupFormValues) => {
        const gid = Number(groupId)

        const existingParts = await api.serviceGroupParts.list({ service_group_id: gid } as any)
        const existingPartIds = (((existingParts as any)?.data) ?? []).map((r: any) => r.id)
        await Promise.all(existingPartIds.map((id: any) => api.serviceGroupParts.destroy(String(id))))
        await Promise.all(
            (values.parts ?? [])
                .filter((p) => p.part?.value)
                .map((p) =>
                    api.serviceGroupParts.create({
                        service_group_id: gid,
                        part_id: Number(p.part!.value),
                        quantity: Number(p.quantity ?? 1),
                        rate: Number(p.rate ?? 0),
                    } as any),
                ),
        )

        const existingServices = await api.serviceGroupServices.list({ service_group_id: gid } as any)
        const existingServiceIds = (((existingServices as any)?.data) ?? []).map((r: any) => r.id)
        await Promise.all(existingServiceIds.map((id: any) => api.serviceGroupServices.destroy(String(id))))
        await Promise.all(
            (values.services ?? [])
                .filter((s) => s.service?.value)
                .map((s) =>
                    api.serviceGroupServices.create({
                        service_group_id: gid,
                        service_id: Number(s.service!.value),
                        rate: Number(s.rate ?? 0),
                        hours: Number(s.hours ?? 0),
                    } as any),
                ),
        )
    }

    const { mutate, error, isPending } = useFormMutation(form, {
        mutationFn: (values: ServiceGroupFormValues) => {
            const run = async () => {
                const groupRes: any =
                    isEditing && resourceId
                        ? await api.serviceGroups.update(resourceId, mapUpdatePayload(values))
                        : await api.serviceGroups.create(mapCreatePayload(values))
                const groupId = resourceId ?? groupRes?.data?.id ?? groupRes?.id
                if (groupId) {
                    await syncIncludes(groupId, values)
                }
                return groupRes
            }
            const promise = run()
            toast.promise(promise, {
                loading: isEditing ? "Updating package..." : "Creating package...",
                success: isEditing ? "Package updated" : "Package created",
                error: isEditing ? "Failed to update package" : "Failed to create package",
            })
            return promise
        },
        onSuccess: () => {
            form.reset()
            onSuccess?.()
        },
    })

    return (
        <Rhform form={form} onSubmit={(values) => mutate(values)}>
            {error && (
                <Alert variant="destructive" className="mb-4">
                    <AlertTriangle className="me-2 h-4 w-4" />
                    <AlertTitle>
                        {isEditing ? "Failed to update service group" : "Failed to create service group"}
                    </AlertTitle>
                    {error.message}
                </Alert>
            )}

            <FieldGroup>
                <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
                    <RhfTextField
                        name="service_name"
                        label="Service Name"
                        placeholder="e.g. Engine Service Group"
                        required
                    />
                    <RhfTextField
                        name="code"
                        label="Code"
                        placeholder="e.g. SG-001"
                    />
                </div>

                {!isEditing && (
                    <>
                        <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
                            <RhfAsyncSelectField
                                name="shop_type"
                                label="Shop Type"
                                placeholder="Select shop type"
                                queryKey={["shop-types"]}
                                listFn={() => api.shopTypes.list()}
                                mapOption={mapLookupOption}
                                createForm={(props) => <ShopTypeInlineForm {...props} />}
                                createLabel="Shop Type"
                                {...STORE_OBJECT}
                            />
                            <RhfAsyncSelectField
                                name="inventory_category"
                                label="Category"
                                placeholder="Select category"
                                queryKey={["inventory-categories"]}
                                listFn={() => api.inventory.listCategories()}
                                mapOption={mapLookupOption}
                                createForm={(props) => <InventoryCategoryInlineForm {...props} />}
                                createLabel="Category"
                                {...STORE_OBJECT}
                            />
                        </div>

                        <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
                            <RhfAsyncSelectField
                                name="unit_type"
                                label="Unit Type"
                                placeholder="Select unit type"
                                queryKey={["unit-types"]}
                                listFn={() => api.inventory.listUnitTypes()}
                                mapOption={mapLookupOption}
                                createForm={(props) => <UnitTypeInlineForm {...props} />}
                                createLabel="Unit Type"
                                {...STORE_OBJECT}
                            />
                            <RhfAsyncSelectField
                                name="department"
                                label="Department"
                                placeholder="Select department"
                                queryKey={["departments"]}
                                listFn={() => api.departments.list()}
                                mapOption={(item: any) => ({ value: String(item.id), label: item.name ?? String(item.id) })}
                                createForm={(props) => <DepartmentInlineForm {...props} />}
                                createLabel="Department"
                                {...STORE_OBJECT}
                            />
                        </div>
                    </>
                )}

                <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
                    <RhfTextField
                        name="selling_price"
                        label="Selling Price (AED)"
                        placeholder="0.00"
                        type="number"
                    />
                    <RhfTextField
                        name="selling_chart_of_account"
                        label="Selling Chart of Account"
                        placeholder="e.g. 4000"
                    />
                </div>

                <RhfTextareaField
                    name="service_description"
                    label="Description"
                    placeholder="Optional description"
                    rows={3}
                />

                {/* ── Parts in this package ── */}
                <div className="border-t pt-4">
                    <div className="mb-2 flex items-center justify-between">
                        <h3 className="text-sm font-semibold">Parts in this package</h3>
                        <Button
                            type="button"
                            variant="outline"
                            size="sm"
                            onClick={() => partsArray.append({ part: null, quantity: 1, rate: 0 })}
                        >
                            <Plus className="me-1 h-4 w-4" /> Add Part
                        </Button>
                    </div>
                    {partsArray.fields.length === 0 && (
                        <p className="text-muted-foreground text-sm">No parts added yet.</p>
                    )}
                    <div className="space-y-3">
                        {partsArray.fields.map((field, index) => (
                            <div
                                key={field.id}
                                className="grid grid-cols-1 gap-2 sm:grid-cols-[1fr_110px_130px_auto] sm:items-end"
                            >
                                <RhfAsyncSelectField
                                    name={`parts.${index}.part`}
                                    label="Part"
                                    placeholder="Select part (e.g. Engine Oil 5W-30)"
                                    queryKey={["parts"]}
                                    listFn={() => api.parts.list()}
                                    mapOption={mapLookupOption}
                                    {...STORE_OBJECT}
                                />
                                <RhfTextField name={`parts.${index}.quantity`} label="Qty" type="number" placeholder="1" />
                                <RhfTextField name={`parts.${index}.rate`} label="Rate (AED)" type="number" placeholder="0.00" />
                                <Button
                                    type="button"
                                    variant="ghost"
                                    size="icon"
                                    onClick={() => partsArray.remove(index)}
                                    aria-label="Remove part"
                                >
                                    <Trash2 className="h-4 w-4 text-red-600" />
                                </Button>
                            </div>
                        ))}
                    </div>
                </div>

                {/* ── Services in this package ── */}
                <div className="border-t pt-4">
                    <div className="mb-2 flex items-center justify-between">
                        <h3 className="text-sm font-semibold">Services in this package</h3>
                        <Button
                            type="button"
                            variant="outline"
                            size="sm"
                            onClick={() => servicesArray.append({ service: null, rate: 0, hours: 0 })}
                        >
                            <Plus className="me-1 h-4 w-4" /> Add Service
                        </Button>
                    </div>
                    {servicesArray.fields.length === 0 && (
                        <p className="text-muted-foreground text-sm">No services added yet.</p>
                    )}
                    <div className="space-y-3">
                        {servicesArray.fields.map((field, index) => (
                            <div
                                key={field.id}
                                className="grid grid-cols-1 gap-2 sm:grid-cols-[1fr_110px_130px_auto] sm:items-end"
                            >
                                <RhfAsyncSelectField
                                    name={`services.${index}.service`}
                                    label="Service"
                                    placeholder="Select service (e.g. Oil change labour)"
                                    queryKey={["services"]}
                                    listFn={() => api.services.list()}
                                    mapOption={mapLookupOption}
                                    {...STORE_OBJECT}
                                />
                                <RhfTextField name={`services.${index}.hours`} label="Hours" type="number" placeholder="0" />
                                <RhfTextField name={`services.${index}.rate`} label="Rate (AED)" type="number" placeholder="0.00" />
                                <Button
                                    type="button"
                                    variant="ghost"
                                    size="icon"
                                    onClick={() => servicesArray.remove(index)}
                                    aria-label="Remove service"
                                >
                                    <Trash2 className="h-4 w-4 text-red-600" />
                                </Button>
                            </div>
                        ))}
                    </div>
                </div>

                <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
                    <RhfCheckboxField
                        name="show_as_lump_sum"
                        label="Show as Lump Sum"
                    />
                    <RhfCheckboxField
                        name="mark_as_recommended"
                        label="Recommended"
                    />
                    <RhfCheckboxField
                        name="set_packaged_pricing"
                        label="Set Packaged Pricing"
                    />
                    <RhfCheckboxField
                        name="is_active"
                        label="Active"
                    />
                </div>


            </FieldGroup>

            <div className="mt-4 flex justify-end">
                <Button type="submit" disabled={isPending}>
                    {isEditing ? <Save className="me-2 h-4 w-4" /> : <Plus className="me-2 h-4 w-4" />}
                    {isPending
                        ? isEditing ? "Updating..." : "Creating..."
                        : isEditing ? "Update Service Group" : "Create Service Group"}
                </Button>
            </div>
        </Rhform>
    )
}
