"use client"

import { useState, type ReactNode } from "react"
import { useController, useFormContext, type FieldValues, type FieldPath } from "react-hook-form"
import { Button } from "@/shared/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card"
import { Field, FieldError } from "@/shared/components/ui/field"
import { Plus } from "lucide-react"
import {
    ResourceSelectorDialog,
    type ResourceSelectorDialogProps,
} from "./resource-selector-dialog"
import type { ResourcePageClient, ResourceItem } from "@/shared/data-view/resource-page"

export type RhfResourceFieldProps<
    TValues extends FieldValues,
    TName extends FieldPath<TValues>,
    TClient extends ResourcePageClient,
> = {
    /** RHF field name — value is an array of items after mapping */
    name: TName
    /** Label displayed on the card header */
    label: string
    /** Button text for the trigger */
    triggerLabel?: string
    /** Map a selected resource row into the form item shape */
    mapSelected: (row: ResourceItem<TClient>) => TValues[TName][number]
    /** Render the list of selected items inside the card */
    renderItems: (
        items: TValues[TName],
        helpers: {
            remove: (index: number) => void
            update: (index: number, item: TValues[TName][number]) => void
            replace: (items: TValues[TName]) => void
        },
    ) => ReactNode
    /** Props forwarded to ResourceSelectorDialog (columns, routeKey, getClient, etc.) */
    dialogProps: Omit<
        ResourceSelectorDialogProps<TClient>,
        "open" | "onOpenChange" | "onConfirm"
    >
    /** Deduplicate by this key when merging new selections. Defaults to "id" */
    itemKey?: string
}

export function RhfResourceField<
    TValues extends FieldValues,
    TName extends FieldPath<TValues>,
    TClient extends ResourcePageClient,
>({
    name,
    label,
    triggerLabel,
    mapSelected,
    renderItems,
    dialogProps,
    itemKey = "id",
}: RhfResourceFieldProps<TValues, TName, TClient>) {
    const { control } = useFormContext<TValues>()
    const {
        field,
        fieldState: { error },
    } = useController({ name, control })

    const [open, setOpen] = useState(false)

    const items: TValues[TName] = field.value ?? ([] as unknown as TValues[TName])

    const handleConfirm = (rows: ResourceItem<TClient>[]) => {
        const mapped = rows.map(mapSelected)
        // Merge: keep existing items, add new ones (deduplicate by itemKey)
        const existingKeys = new Set(
            (items as any[]).map((item: any) => String(item[itemKey])),
        )
        const newItems = mapped.filter(
            (item: any) => !existingKeys.has(String(item[itemKey])),
        )
        field.onChange([...items, ...newItems])
    }

    const helpers = {
        remove: (index: number) => {
            const next = [...(items as any[])]
            next.splice(index, 1)
            field.onChange(next)
        },
        update: (index: number, item: TValues[TName][number]) => {
            const next = [...(items as any[])]
            next[index] = item
            field.onChange(next)
        },
        replace: (newItems: TValues[TName]) => {
            field.onChange(newItems)
        },
    }

    return (
        <Field data-invalid={!!error || undefined}>
            <Card>
                <CardHeader className=" flex justify-between items-center">
                    <span className="text-base font-medium">{label}</span>
                    <Button
                        type="button"
                        size="sm"
                        variant="outline"
                        onClick={() => setOpen(true)}
                    >
                        <Plus className="mr-1.5 h-4 w-4" />
                        {triggerLabel ?? label}
                    </Button>
                </CardHeader>
                {
                    items.length > 0 &&
                    <CardContent>
                        {(items as any[]).length > 0
                            && renderItems(items, helpers)
                        }
                    </CardContent>
                }
            </Card>
            {error && <FieldError>{error.message}</FieldError>}
            <ResourceSelectorDialog<TClient>
                {...dialogProps}
                open={open}
                onOpenChange={setOpen}
                onConfirm={handleConfirm}
            />
        </Field>
    )
}
