import { Head, Link, router, useForm } from '@inertiajs/react';
import {
    ArrowLeft,
    Boxes,
    ExternalLink,
    FileText,
    PackageCheck,
    Pencil,
    Plus,
    Trash2,
} from 'lucide-react';
import { useState } from 'react';
import {
    Callout,
    EmptyState,
    KeyValueGrid,
    PageHeader,
    SectionCard,
} from '@/components/crm/page-header';
import { Field } from '@/components/crm/form-field';
import { NativeSelect } from '@/components/crm/native-select';
import {
    StockStatusBadge,
    VerificationBadge,
} from '@/components/crm/stock-badge';
import { DataPagination } from '@/components/crm/toolbar';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import {
    Table,
    TableBody,
    TableCell,
    TableHead,
    TableHeader,
    TableRow,
} from '@/components/ui/table';
import { cn } from '@/lib/utils';
import {
    index as productsIndex,
    edit as productEdit,
} from '@/routes/warehouse/products';
import { store as storeMovement } from '@/routes/warehouse/products/movements';
import {
    destroy as destroySupplier,
    store as storeSupplier,
} from '@/routes/warehouse/products/suppliers';
import { index as suppliersIndex } from '@/routes/warehouse/suppliers';
import type {
    Paginated,
    ProductDetail,
    StockMovementRow,
    WarehouseAbilities,
} from '@/types';

/**
 * The movement types a person records by hand.
 *
 * `picked`, `dispatched`, `transferred` and `reconciled` are ledger steps used
 * by later phases (picking lists and stocktakes) rather than buttons here. A
 * correction is listed separately because it needs a different permission.
 */
const movementTypes = [
    {
        value: 'received',
        label: 'Goods received',
        description: 'Stock that has arrived and is now on the shelf.',
    },
    {
        value: 'issued',
        label: 'Issued to a job',
        description:
            'Stock that has left the warehouse. Any reservation for it is consumed at the same time.',
    },
    {
        value: 'returned',
        label: 'Returned to stock',
        description: 'Sellable stock that came back from a job.',
    },
    {
        value: 'reserved',
        label: 'Reserved for a job',
        description:
            'Promised to a job. It stays on the shelf but is no longer available to another job.',
    },
    {
        value: 'released',
        label: 'Reservation released',
        description: 'A promise that is no longer needed.',
    },
    {
        value: 'damaged',
        label: 'Marked damaged',
        description:
            'Present in the building but not sellable. Available stock drops immediately.',
    },
    {
        value: 'corrected',
        label: 'Count correction',
        description:
            'The quantity actually counted. Needs the stock adjustment permission and a reason.',
    },
];

export default function ProductShow({
    product,
    movements,
    supplierOptions,
    can,
}: {
    product: ProductDetail;
    movements: Paginated<StockMovementRow>;
    supplierOptions: Array<{ value: number; label: string }>;
    can: WarehouseAbilities;
}) {
    const [showSupplierForm, setShowSupplierForm] = useState(false);

    const movementForm = useForm({
        type: 'received',
        quantity: '',
        reason: '',
        reference: '',
    });

    const supplierForm = useForm({
        supplier_id: '',
        supplier_product_code: '',
        supplier_url: '',
        unit_cost: '',
        is_preferred: false,
    });

    const availableTypes = movementTypes.filter(
        (type) => type.value !== 'corrected' || can.adjust,
    );
    const selectedType =
        availableTypes.find((type) => type.value === movementForm.data.type) ??
        availableTypes[0];
    const isCorrection = movementForm.data.type === 'corrected';

    const submitMovement = () => {
        movementForm.post(storeMovement(product.id).url, {
            preserveScroll: true,
            onSuccess: () => {
                movementForm.reset('quantity', 'reason', 'reference');
            },
        });
    };

    const submitSupplier = () => {
        supplierForm.post(storeSupplier(product.id).url, {
            preserveScroll: true,
            onSuccess: () => {
                supplierForm.reset();
                setShowSupplierForm(false);
            },
        });
    };

    return (
        <>
            <Head title={`${product.name} · ${product.sku}`} />

            <div className="flex flex-col gap-5">
                <PageHeader
                    eyebrow={
                        <>
                            <Link
                                href={productsIndex().url}
                                className="inline-flex items-center gap-1.5 hover:text-foreground"
                            >
                                <ArrowLeft className="size-3.5" />
                                Product catalogue
                            </Link>
                            <span aria-hidden>/</span>
                            <span className="font-mono">{product.sku}</span>
                        </>
                    }
                    title={product.name}
                    description={product.description}
                    actions={
                        <>
                            {can.manage ? (
                                <Button variant="outline" size="sm" asChild>
                                    <a href="#record-movement">
                                        <PackageCheck className="size-4" />
                                        Record movement
                                    </a>
                                </Button>
                            ) : null}
                            {can.manage ? (
                                <Button variant="outline" size="sm" asChild>
                                    <Link href={productEdit(product.id).url}>
                                        <Pencil className="size-4" />
                                        Edit
                                    </Link>
                                </Button>
                            ) : null}
                        </>
                    }
                />

                <div className="flex flex-wrap items-center gap-2">
                    <StockStatusBadge status={product.stock_status} />
                    <VerificationBadge verification={product.verification} />
                    {product.category ? (
                        <span className="inline-flex items-center gap-1.5 rounded-full bg-muted px-2 py-0.5 text-[11px] font-medium text-muted-foreground">
                            <Boxes className="size-3" />
                            {product.category.name}
                        </span>
                    ) : null}
                    {!product.is_active ? (
                        <span className="rounded-full bg-muted px-2 py-0.5 text-[11px] font-medium text-muted-foreground">
                            Archived
                        </span>
                    ) : null}
                </div>

                {product.stock_status === 'out' ? (
                    <Callout
                        tone="danger"
                        title="Nothing available to pick"
                        icon={PackageCheck}
                    >
                        On hand {product.physical_quantity}, of which{' '}
                        {product.reserved_quantity} is reserved and{' '}
                        {product.damaged_quantity} is damaged. Record a receipt
                        when stock arrives.
                    </Callout>
                ) : null}

                {product.stock_status === 'low' ? (
                    <Callout
                        tone="warning"
                        title={`At or below the minimum of ${product.minimum_stock}`}
                        icon={PackageCheck}
                    >
                        {product.available_quantity} available.{' '}
                        {product.reorder_quantity > 0
                            ? `The reorder quantity on file is ${product.reorder_quantity}.`
                            : 'Set a reorder quantity on the product to make replenishment easier.'}
                    </Callout>
                ) : null}

                <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
                    {[
                        {
                            label: 'On hand',
                            value: product.physical_quantity,
                            hint: 'Physically in the building, damaged units included',
                        },
                        {
                            label: 'Reserved',
                            value: product.reserved_quantity,
                            hint: 'Promised to a job and not available to another',
                        },
                        {
                            label: 'Damaged',
                            value: product.damaged_quantity,
                            hint: 'Present but unsellable',
                        },
                        {
                            label: 'Available',
                            value: product.available_quantity,
                            hint: 'What the next job can actually be promised',
                        },
                    ].map((metric) => (
                        <div
                            key={metric.label}
                            className="rounded-xl bg-card px-4 py-3.5 shadow-card ring-1 ring-hairline"
                        >
                            <p className="crm-label">{metric.label}</p>
                            <p className="mt-1 text-2xl font-semibold tracking-tight crm-num">
                                {metric.value.toLocaleString('en-AU')}
                                <span className="ml-1 text-xs font-normal text-muted-foreground">
                                    {product.unit_label}
                                </span>
                            </p>
                            <p className="mt-1 text-xs leading-snug text-muted-foreground">
                                {metric.hint}
                            </p>
                        </div>
                    ))}
                </div>

                <div className="grid gap-5 lg:grid-cols-[minmax(0,1.55fr)_minmax(0,1fr)]">
                    <div className="flex min-w-0 flex-col gap-5">
                        {can.manage ? (
                            <SectionCard
                                id="record-movement"
                                title="Record a movement"
                                description="Every quantity change is a ledger row naming the person who recorded it."
                                icon={PackageCheck}
                                tone="solar"
                            >
                                <form
                                    onSubmit={(event) => {
                                        event.preventDefault();
                                        submitMovement();
                                    }}
                                    className="flex flex-col gap-4"
                                >
                                    <div className="grid gap-4 sm:grid-cols-2">
                                        <Field
                                            label="Movement"
                                            htmlFor="type"
                                            error={movementForm.errors.type}
                                            required
                                        >
                                            <NativeSelect
                                                id="type"
                                                value={movementForm.data.type}
                                                onChange={(event) =>
                                                    movementForm.setData(
                                                        'type',
                                                        event.target.value,
                                                    )
                                                }
                                            >
                                                {availableTypes.map((type) => (
                                                    <option
                                                        key={type.value}
                                                        value={type.value}
                                                    >
                                                        {type.label}
                                                    </option>
                                                ))}
                                            </NativeSelect>
                                        </Field>

                                        <Field
                                            label={
                                                isCorrection
                                                    ? 'Counted quantity'
                                                    : 'Quantity'
                                            }
                                            htmlFor="quantity"
                                            error={movementForm.errors.quantity}
                                            hint={
                                                isCorrection
                                                    ? 'The total on the shelf now'
                                                    : `In ${product.unit_label}`
                                            }
                                            required
                                        >
                                            <Input
                                                id="quantity"
                                                type="number"
                                                min={0}
                                                value={
                                                    movementForm.data.quantity
                                                }
                                                onChange={(event) =>
                                                    movementForm.setData(
                                                        'quantity',
                                                        event.target.value,
                                                    )
                                                }
                                                required
                                            />
                                        </Field>
                                    </div>

                                    <p className="rounded-lg bg-muted/40 px-3 py-2 text-xs leading-relaxed text-muted-foreground">
                                        {selectedType?.description}
                                    </p>

                                    <div className="grid gap-4 sm:grid-cols-2">
                                        <Field
                                            label="Reason"
                                            htmlFor="reason"
                                            error={movementForm.errors.reason}
                                            hint={
                                                isCorrection
                                                    ? 'Required, kept with the record'
                                                    : 'Optional context'
                                            }
                                            required={isCorrection}
                                        >
                                            <Input
                                                id="reason"
                                                value={movementForm.data.reason}
                                                onChange={(event) =>
                                                    movementForm.setData(
                                                        'reason',
                                                        event.target.value,
                                                    )
                                                }
                                                placeholder={
                                                    isCorrection
                                                        ? 'Stocktake found three fewer'
                                                        : 'Delivery docket 1234'
                                                }
                                            />
                                        </Field>

                                        <Field
                                            label="Reference"
                                            htmlFor="reference"
                                            error={
                                                movementForm.errors.reference
                                            }
                                            hint="Purchase order or docket"
                                        >
                                            <Input
                                                id="reference"
                                                value={
                                                    movementForm.data.reference
                                                }
                                                onChange={(event) =>
                                                    movementForm.setData(
                                                        'reference',
                                                        event.target.value,
                                                    )
                                                }
                                            />
                                        </Field>
                                    </div>

                                    <div className="flex justify-end">
                                        <Button
                                            type="submit"
                                            disabled={movementForm.processing}
                                        >
                                            <PackageCheck className="size-4" />
                                            Record movement
                                        </Button>
                                    </div>
                                </form>
                            </SectionCard>
                        ) : null}

                        <SectionCard
                            title="Stock ledger"
                            description="Newest first. Nothing here is edited; a mistake is corrected by another movement."
                            icon={FileText}
                            tone="info"
                            flush
                        >
                            {movements.data.length === 0 ? (
                                <EmptyState
                                    icon={FileText}
                                    title="No movements recorded"
                                    description="The first receipt or correction will appear here."
                                />
                            ) : (
                                <>
                                    <div className="crm-scroll overflow-x-auto">
                                        <Table>
                                            <TableHeader>
                                                <TableRow className="hover:bg-transparent">
                                                    <TableHead className="bg-surface/60 text-[11px] font-semibold tracking-wide uppercase">
                                                        When
                                                    </TableHead>
                                                    <TableHead className="bg-surface/60 text-[11px] font-semibold tracking-wide uppercase">
                                                        Movement
                                                    </TableHead>
                                                    <TableHead className="bg-surface/60 text-right text-[11px] font-semibold tracking-wide uppercase">
                                                        Change
                                                    </TableHead>
                                                    <TableHead className="bg-surface/60 text-right text-[11px] font-semibold tracking-wide uppercase">
                                                        Balance
                                                    </TableHead>
                                                    <TableHead className="bg-surface/60 text-[11px] font-semibold tracking-wide uppercase">
                                                        Detail
                                                    </TableHead>
                                                    <TableHead className="bg-surface/60 text-[11px] font-semibold tracking-wide uppercase">
                                                        By
                                                    </TableHead>
                                                </TableRow>
                                            </TableHeader>
                                            <TableBody>
                                                {movements.data.map(
                                                    (movement) => (
                                                        <TableRow
                                                            key={movement.id}
                                                        >
                                                            <TableCell className="text-xs whitespace-nowrap text-muted-foreground">
                                                                {
                                                                    movement.occurred_at
                                                                }
                                                            </TableCell>
                                                            <TableCell className="text-sm">
                                                                {
                                                                    movement
                                                                        .type
                                                                        .label
                                                                }
                                                            </TableCell>
                                                            <TableCell
                                                                className={cn(
                                                                    'text-right font-medium tabular-nums crm-num',
                                                                    movement.quantity >
                                                                        0 &&
                                                                        'text-success',
                                                                    movement.quantity <
                                                                        0 &&
                                                                        'text-danger',
                                                                )}
                                                            >
                                                                {movement.quantity >
                                                                0
                                                                    ? '+'
                                                                    : ''}
                                                                {
                                                                    movement.quantity
                                                                }
                                                            </TableCell>
                                                            <TableCell className="text-right tabular-nums crm-num">
                                                                {
                                                                    movement.balance_after
                                                                }
                                                            </TableCell>
                                                            <TableCell className="max-w-[16rem] text-xs text-muted-foreground">
                                                                {movement.reason ??
                                                                    movement.reference ??
                                                                    (movement.job
                                                                        ? `Job ${movement.job.job_number}`
                                                                        : '—')}
                                                            </TableCell>
                                                            <TableCell className="text-xs whitespace-nowrap text-muted-foreground">
                                                                {movement.user ??
                                                                    'System'}
                                                            </TableCell>
                                                        </TableRow>
                                                    ),
                                                )}
                                            </TableBody>
                                        </Table>
                                    </div>
                                    <DataPagination
                                        page={movements}
                                        noun="movements"
                                    />
                                </>
                            )}
                        </SectionCard>
                    </div>

                    <div className="flex min-w-0 flex-col gap-5">
                        <SectionCard
                            title="Details"
                            description="What the catalogue holds for this line."
                            icon={Boxes}
                        >
                            <KeyValueGrid
                                columns={1}
                                items={[
                                    {
                                        label: 'Stock code',
                                        value: (
                                            <span className="font-mono">
                                                {product.sku}
                                            </span>
                                        ),
                                    },
                                    {
                                        label: 'Category',
                                        value: product.category?.name,
                                    },
                                    { label: 'Brand', value: product.brand },
                                    {
                                        label: 'Manufacturer',
                                        value: product.manufacturer,
                                    },
                                    {
                                        label: 'Model number',
                                        value: product.model_number,
                                    },
                                    {
                                        label: 'Counted in',
                                        value: product.unit_label,
                                    },
                                    {
                                        label: 'Storage location',
                                        value: product.storage_location,
                                    },
                                    {
                                        label: 'Warranty',
                                        value:
                                            product.warranty_months === null
                                                ? null
                                                : `${product.warranty_months} months`,
                                    },
                                    {
                                        label: 'Traced by',
                                        value:
                                            product.tracks_serial_numbers ||
                                            product.tracks_batches
                                                ? [
                                                      product.tracks_serial_numbers
                                                          ? 'Serial number'
                                                          : null,
                                                      product.tracks_batches
                                                          ? 'Batch number'
                                                          : null,
                                                  ]
                                                      .filter(Boolean)
                                                      .join(' and ')
                                                : null,
                                    },
                                ]}
                            />
                        </SectionCard>

                        {product.specifications.length > 0 ? (
                            <SectionCard
                                title="Specifications"
                                description="Specific to this kind of product."
                                icon={FileText}
                            >
                                <KeyValueGrid
                                    columns={1}
                                    items={product.specifications.map(
                                        (specification) => ({
                                            label: specification.label,
                                            value: specification.value,
                                        }),
                                    )}
                                />
                            </SectionCard>
                        ) : null}

                        <SectionCard
                            title="Suppliers"
                            description="Who the company can buy this from."
                            icon={ExternalLink}
                            actions={
                                can.manageSuppliers ? (
                                    <Button
                                        variant="outline"
                                        size="sm"
                                        onClick={() =>
                                            setShowSupplierForm((open) => !open)
                                        }
                                    >
                                        <Plus className="size-4" />
                                        Link supplier
                                    </Button>
                                ) : undefined
                            }
                        >
                            <div className="flex flex-col gap-3">
                                {product.suppliers.length === 0 ? (
                                    <p className="text-xs leading-relaxed text-muted-foreground">
                                        No supplier is linked. Add one from{' '}
                                        <Link
                                            href={suppliersIndex().url}
                                            className="underline underline-offset-2"
                                        >
                                            Suppliers
                                        </Link>{' '}
                                        and link it here with its product code.
                                    </p>
                                ) : null}

                                {product.suppliers.map((supplier) => (
                                    <div
                                        key={supplier.id}
                                        className="flex items-start justify-between gap-3 border-b border-hairline pb-3 last:border-0 last:pb-0"
                                    >
                                        <div className="min-w-0">
                                            <p className="flex flex-wrap items-center gap-2 text-sm font-medium">
                                                {supplier.name}
                                                {supplier.is_preferred ? (
                                                    <span className="rounded-full bg-solar-soft px-1.5 py-0.5 text-[10px] font-semibold tracking-wide text-solar-ink uppercase">
                                                        Preferred
                                                    </span>
                                                ) : null}
                                            </p>
                                            <p className="mt-0.5 font-mono text-xs text-muted-foreground">
                                                {supplier.product_code ??
                                                    'No supplier code'}
                                            </p>
                                            <p className="mt-1 text-xs text-muted-foreground">
                                                {[
                                                    supplier.pivot_lead_time_days !==
                                                    null
                                                        ? `${supplier.pivot_lead_time_days} day lead time`
                                                        : null,
                                                    can.viewCosts &&
                                                    supplier.unit_cost !== null
                                                        ? `$${supplier.unit_cost} per ${product.unit}`
                                                        : null,
                                                ]
                                                    .filter(Boolean)
                                                    .join(' · ') ||
                                                    'No terms recorded'}
                                            </p>
                                        </div>
                                        {can.manageSuppliers ? (
                                            <Button
                                                variant="ghost"
                                                size="icon"
                                                aria-label={`Unlink ${supplier.name}`}
                                                onClick={() => {
                                                    if (
                                                        window.confirm(
                                                            `Unlink ${supplier.name} from this product? The supplier itself is kept.`,
                                                        )
                                                    ) {
                                                        router.delete(
                                                            destroySupplier({
                                                                product:
                                                                    product.id,
                                                                supplier:
                                                                    supplier.id,
                                                            }).url,
                                                            {
                                                                preserveScroll: true,
                                                            },
                                                        );
                                                    }
                                                }}
                                            >
                                                <Trash2 className="size-4" />
                                            </Button>
                                        ) : null}
                                    </div>
                                ))}

                                {can.manageSuppliers &&
                                showSupplierForm &&
                                supplierOptions.length > 0 ? (
                                    <form
                                        onSubmit={(event) => {
                                            event.preventDefault();
                                            submitSupplier();
                                        }}
                                        className="flex flex-col gap-3 rounded-lg bg-muted/30 p-3"
                                    >
                                        <Field
                                            label="Supplier"
                                            htmlFor="supplier_id"
                                            error={
                                                supplierForm.errors.supplier_id
                                            }
                                            required
                                        >
                                            <NativeSelect
                                                id="supplier_id"
                                                value={
                                                    supplierForm.data
                                                        .supplier_id
                                                }
                                                onChange={(event) =>
                                                    supplierForm.setData(
                                                        'supplier_id',
                                                        event.target.value,
                                                    )
                                                }
                                                required
                                            >
                                                <option value="">
                                                    Choose a supplier
                                                </option>
                                                {supplierOptions.map(
                                                    (option) => (
                                                        <option
                                                            key={option.value}
                                                            value={String(
                                                                option.value,
                                                            )}
                                                        >
                                                            {option.label}
                                                        </option>
                                                    ),
                                                )}
                                            </NativeSelect>
                                        </Field>

                                        <Field
                                            label="Supplier's product code"
                                            htmlFor="supplier_product_code"
                                            error={
                                                supplierForm.errors
                                                    .supplier_product_code
                                            }
                                        >
                                            <Input
                                                id="supplier_product_code"
                                                value={
                                                    supplierForm.data
                                                        .supplier_product_code
                                                }
                                                onChange={(event) =>
                                                    supplierForm.setData(
                                                        'supplier_product_code',
                                                        event.target.value,
                                                    )
                                                }
                                            />
                                        </Field>

                                        {can.viewCosts ? (
                                            <Field
                                                label="Unit cost"
                                                htmlFor="unit_cost"
                                                error={
                                                    supplierForm.errors
                                                        .unit_cost
                                                }
                                            >
                                                <Input
                                                    id="unit_cost"
                                                    type="number"
                                                    step="0.01"
                                                    min={0}
                                                    value={
                                                        supplierForm.data
                                                            .unit_cost
                                                    }
                                                    onChange={(event) =>
                                                        supplierForm.setData(
                                                            'unit_cost',
                                                            event.target.value,
                                                        )
                                                    }
                                                />
                                            </Field>
                                        ) : null}

                                        <label className="flex items-center gap-2 text-sm">
                                            <Checkbox
                                                checked={
                                                    supplierForm.data
                                                        .is_preferred
                                                }
                                                onCheckedChange={(checked) =>
                                                    supplierForm.setData(
                                                        'is_preferred',
                                                        checked === true,
                                                    )
                                                }
                                            />
                                            Preferred supplier
                                        </label>

                                        <div className="flex justify-end gap-2">
                                            <Button
                                                type="button"
                                                variant="ghost"
                                                size="sm"
                                                onClick={() =>
                                                    setShowSupplierForm(false)
                                                }
                                            >
                                                Cancel
                                            </Button>
                                            <Button
                                                type="submit"
                                                size="sm"
                                                disabled={
                                                    supplierForm.processing
                                                }
                                            >
                                                Link
                                            </Button>
                                        </div>
                                    </form>
                                ) : null}
                            </div>
                        </SectionCard>

                        <SectionCard
                            title="Provenance"
                            description="How much this row is actually known to be."
                            icon={FileText}
                        >
                            <p className="text-sm">
                                {product.verification_description}
                            </p>
                            <div className="mt-3 flex flex-col gap-2 text-xs">
                                {product.source_url ? (
                                    <a
                                        href={product.source_url}
                                        target="_blank"
                                        rel="noreferrer"
                                        className="inline-flex items-center gap-1.5 text-solar-ink hover:underline"
                                    >
                                        <ExternalLink className="size-3.5" />
                                        Source page
                                    </a>
                                ) : null}
                                {product.datasheet_url ? (
                                    <a
                                        href={product.datasheet_url}
                                        target="_blank"
                                        rel="noreferrer"
                                        className="inline-flex items-center gap-1.5 text-solar-ink hover:underline"
                                    >
                                        <FileText className="size-3.5" />
                                        Datasheet
                                    </a>
                                ) : null}
                                {product.source_reviewed_on ? (
                                    <p className="text-muted-foreground">
                                        Reviewed {product.source_reviewed_on}
                                    </p>
                                ) : null}
                                <p className="text-muted-foreground">
                                    Added {product.created_at ?? '—'}
                                    {product.updated_by
                                        ? ` · last changed by ${product.updated_by}`
                                        : ''}
                                </p>
                            </div>
                        </SectionCard>
                    </div>
                </div>
            </div>
        </>
    );
}
