import { Head, router, useForm } from '@inertiajs/react';
import type { ColumnDef } from '@tanstack/react-table';
import type { FormEvent } from 'react';
import { useMemo, useState } from 'react';
import { DataTable } from '@/components/data-table';
import { FormField } from '@/components/form-field';
import { EmptyState } from '@/components/layout/empty-state';
import { FormDrawer } from '@/components/layout/form-drawer';
import { PageHeader } from '@/components/layout/page-header';
import { SectionCard } from '@/components/layout/section-card';
import { LocationMultiSelect } from '@/components/location-multi-select';
import type { LocationOption } from '@/components/location-multi-select';
import { MoneyInput } from '@/components/money-input';
import { ResourceActionsMenu } from '@/components/resource-actions-menu';
import { StatusBadge } from '@/components/status-badge';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { NativeSelect } from '@/components/ui/native-select';
import { SheetFooter } from '@/components/ui/sheet';
import { Switch } from '@/components/ui/switch';
import { Textarea } from '@/components/ui/textarea';
import AppLayout from '@/layouts/app-layout';
import { centsToDisplay } from '@/lib/money';
import adminDiscounts from '@/routes/admin/discounts';

type PackageOption = { id: number; name: string };
type AddonOption = { id: number; name: string };
type CustomerOption = { id: number; name: string; email: string };

type Discount = {
    id: number;
    name: string;
    description: string | null;
    method: 'automatic' | 'code';
    class: 'order' | 'service';
    type: 'percentage' | 'fixed_amount' | 'buy_x_get_y';
    code: string | null;
    customer: CustomerOption | null;
    percent_value: string | null;
    fixed_amount_cents: number | null;
    bogo_trigger_type: 'package' | 'addon' | null;
    bogo_trigger_id: number | null;
    bogo_reward_type: 'package' | 'addon' | null;
    bogo_reward_id: number | null;
    bogo_reward_discount_percent: string;
    min_order_amount_cents: number | null;
    max_discount_amount_cents: number | null;
    usage_limit_total: number | null;
    usage_limit_per_customer: number | null;
    times_used: number;
    starts_at: string | null;
    ends_at: string | null;
    is_active: boolean;
    packages: PackageOption[];
    addons: AddonOption[];
    locations: LocationOption[];
};

type Props = {
    discounts: Discount[];
    packages: PackageOption[];
    addons: AddonOption[];
    locations: LocationOption[];
    customers: CustomerOption[];
};

type DiscountFormData = {
    name: string;
    description: string;
    method: 'automatic' | 'code';
    class: 'order' | 'service';
    type: 'percentage' | 'fixed_amount' | 'buy_x_get_y';
    code: string;
    customer_id: number | '';
    percent_value: number | '';
    fixed_amount_cents: number;
    bogo_trigger_type: 'package' | 'addon' | '';
    bogo_trigger_id: number | '';
    bogo_reward_type: 'package' | 'addon' | '';
    bogo_reward_id: number | '';
    bogo_reward_discount_percent: number;
    min_order_amount_cents: number;
    max_discount_amount_cents: number | '';
    usage_limit_total: number | '';
    usage_limit_per_customer: number | '';
    starts_at: string;
    ends_at: string;
    is_active: boolean;
    package_ids: number[];
    addon_ids: number[];
    location_ids: number[];
};

function emptyDiscountForm(): DiscountFormData {
    return {
        name: '',
        description: '',
        method: 'code',
        class: 'order',
        type: 'percentage',
        code: '',
        customer_id: '',
        percent_value: '',
        fixed_amount_cents: 0,
        bogo_trigger_type: '',
        bogo_trigger_id: '',
        bogo_reward_type: '',
        bogo_reward_id: '',
        bogo_reward_discount_percent: 100,
        min_order_amount_cents: 0,
        max_discount_amount_cents: '',
        usage_limit_total: '',
        usage_limit_per_customer: '',
        starts_at: '',
        ends_at: '',
        is_active: true,
        package_ids: [],
        addon_ids: [],
        location_ids: [],
    };
}

function discountToForm(discount: Discount): DiscountFormData {
    return {
        name: discount.name,
        description: discount.description ?? '',
        method: discount.method,
        class: discount.class,
        type: discount.type,
        code: discount.code ?? '',
        customer_id: discount.customer?.id ?? '',
        percent_value: discount.percent_value ? Number(discount.percent_value) : '',
        fixed_amount_cents: discount.fixed_amount_cents ?? 0,
        bogo_trigger_type: discount.bogo_trigger_type ?? '',
        bogo_trigger_id: discount.bogo_trigger_id ?? '',
        bogo_reward_type: discount.bogo_reward_type ?? '',
        bogo_reward_id: discount.bogo_reward_id ?? '',
        bogo_reward_discount_percent: Number(discount.bogo_reward_discount_percent ?? 100),
        min_order_amount_cents: discount.min_order_amount_cents ?? 0,
        max_discount_amount_cents: discount.max_discount_amount_cents ?? '',
        usage_limit_total: discount.usage_limit_total ?? '',
        usage_limit_per_customer: discount.usage_limit_per_customer ?? '',
        starts_at: discount.starts_at ? discount.starts_at.slice(0, 10) : '',
        ends_at: discount.ends_at ? discount.ends_at.slice(0, 10) : '',
        is_active: discount.is_active,
        package_ids: discount.packages.map((p) => p.id),
        addon_ids: discount.addons.map((a) => a.id),
        location_ids: discount.locations.map((l) => l.id),
    };
}

function valueSummary(discount: Discount): string {
    if (discount.type === 'percentage') {
        return `${Number(discount.percent_value ?? 0)}% off`;
    }

    if (discount.type === 'fixed_amount') {
        return `$${centsToDisplay(discount.fixed_amount_cents ?? 0)} off`;
    }

    return `Buy ${discount.bogo_trigger_type ?? 'item'}, get ${discount.bogo_reward_type ?? 'item'} at ${Number(discount.bogo_reward_discount_percent)}% off`;
}

function CheckboxList({
    items,
    selectedIds,
    onChange,
    emptyLabel,
}: {
    items: Array<{ id: number; name: string }>;
    selectedIds: number[];
    onChange: (ids: number[]) => void;
    emptyLabel: string;
}) {
    if (items.length === 0) {
        return <p className="text-sm text-muted-foreground">{emptyLabel}</p>;
    }

    const toggle = (id: number) => {
        onChange(
            selectedIds.includes(id)
                ? selectedIds.filter((existing) => existing !== id)
                : [...selectedIds, id],
        );
    };

    return (
        <div className="flex max-h-40 flex-col gap-2 overflow-y-auto rounded-lg border p-3">
            {items.map((item) => (
                <label
                    key={item.id}
                    className="flex cursor-pointer items-center gap-2 text-sm"
                >
                    <Checkbox
                        checked={selectedIds.includes(item.id)}
                        onCheckedChange={() => toggle(item.id)}
                    />
                    {item.name}
                </label>
            ))}
        </div>
    );
}

export default function AdminDiscountsIndex({
    discounts,
    packages,
    addons,
    locations,
    customers,
}: Props) {
    const [creating, setCreating] = useState(false);
    const [editingDiscount, setEditingDiscount] = useState<Discount | null>(null);

    const createForm = useForm<DiscountFormData>(emptyDiscountForm());
    const editForm = useForm<DiscountFormData>(emptyDiscountForm());

    const openCreate = () => {
        createForm.setData(emptyDiscountForm());
        createForm.clearErrors();
        setCreating(true);
    };

    const closeCreate = () => {
        setCreating(false);
        createForm.reset();
        createForm.clearErrors();
    };

    const submitCreate = (event: FormEvent<HTMLFormElement>) => {
        event.preventDefault();
        createForm.post(adminDiscounts.store.url(), {
            onSuccess: () => closeCreate(),
        });
    };

    const openEdit = (discount: Discount) => {
        setEditingDiscount(discount);
        editForm.setData(discountToForm(discount));
        editForm.clearErrors();
    };

    const closeEdit = () => {
        setEditingDiscount(null);
        editForm.reset();
        editForm.clearErrors();
    };

    const submitEdit = (event: FormEvent<HTMLFormElement>) => {
        event.preventDefault();

        if (!editingDiscount) {
            return;
        }

        editForm.patch(adminDiscounts.update.url({ discount: editingDiscount.id }), {
            onSuccess: () => closeEdit(),
        });
    };

    const deleteDiscount = (discountId: number) => {
        router.delete(adminDiscounts.destroy.url({ discount: discountId }));
    };

    const columns = useMemo<ColumnDef<Discount>[]>(
        () => [
            {
                accessorKey: 'name',
                header: 'Name',
                meta: { label: 'Name' },
                cell: ({ row }) => (
                    <div>
                        <span className="font-medium">{row.original.name}</span>
                        {row.original.code && (
                            <div className="mt-0.5">
                                <Badge variant="secondary">{row.original.code}</Badge>
                            </div>
                        )}
                    </div>
                ),
            },
            {
                accessorKey: 'method',
                header: 'Method',
                meta: { label: 'Method' },
                cell: ({ row }) => (
                    <span className="capitalize">{row.getValue('method')}</span>
                ),
            },
            {
                accessorKey: 'class',
                header: 'Applies to',
                meta: { label: 'Applies to' },
                cell: ({ row }) => (
                    <span className="capitalize">{row.getValue('class')}</span>
                ),
            },
            {
                id: 'value',
                header: 'Value',
                meta: { label: 'Value' },
                cell: ({ row }) => (
                    <span className="text-sm">{valueSummary(row.original)}</span>
                ),
            },
            {
                id: 'usage',
                header: 'Usage',
                meta: { label: 'Usage' },
                cell: ({ row }) =>
                    `${row.original.times_used}${row.original.usage_limit_total ? ` / ${row.original.usage_limit_total}` : ''}`,
            },
            {
                accessorKey: 'is_active',
                header: 'Status',
                meta: { label: 'Status' },
                cell: ({ row }) => (
                    <StatusBadge
                        status={row.getValue('is_active') ? 'active' : 'disabled'}
                    />
                ),
            },
            {
                id: 'actions',
                enableHiding: false,
                header: () => <span className="sr-only">Actions</span>,
                cell: ({ row }) => (
                    <ResourceActionsMenu
                        onEdit={() => openEdit(row.original)}
                        onDelete={() => deleteDiscount(row.original.id)}
                        deleteTitle="Delete discount?"
                        deleteDescription="This permanently removes the discount. Discounts that have already been used cannot be deleted — deactivate them instead."
                    />
                ),
            },
        ],
        [],
    );

    return (
        <>
            <Head title="Discounts & promotions" />
            <div className="flex h-full flex-1 flex-col gap-6">
                <PageHeader
                    title="Discounts & promotions"
                    actions={<Button onClick={openCreate}>New discount</Button>}
                />

                <SectionCard title="All discounts">
                    {discounts.length === 0 ? (
                        <EmptyState title="No discounts yet" />
                    ) : (
                        <DataTable
                            columns={columns}
                            data={discounts}
                            searchPlaceholder="Search discounts..."
                        />
                    )}
                </SectionCard>
            </div>

            <FormDrawer
                open={creating}
                onOpenChange={(open) => {
                    if (!open) {
closeCreate();
}
                }}
                title="New discount"
                direction="right"
            >
                <form onSubmit={submitCreate} className="grid gap-4">
                    <DiscountFormFields
                        form={createForm}
                        idPrefix="create"
                        packages={packages}
                        addons={addons}
                        locations={locations}
                        customers={customers}
                    />
                    <SheetFooter className="px-0 pb-0 sm:flex-row">
                        <Button type="button" variant="outline" onClick={closeCreate}>
                            Cancel
                        </Button>
                        <Button type="submit" disabled={createForm.processing}>
                            Create discount
                        </Button>
                    </SheetFooter>
                </form>
            </FormDrawer>

            <FormDrawer
                open={editingDiscount !== null}
                onOpenChange={(open) => {
                    if (!open) {
closeEdit();
}
                }}
                title="Edit discount"
                direction="right"
            >
                <form onSubmit={submitEdit} className="grid gap-4">
                    <DiscountFormFields
                        form={editForm}
                        idPrefix="edit"
                        packages={packages}
                        addons={addons}
                        locations={locations}
                        customers={customers}
                    />
                    <SheetFooter className="px-0 pb-0 sm:flex-row">
                        <Button type="button" variant="outline" onClick={closeEdit}>
                            Cancel
                        </Button>
                        <Button type="submit" disabled={editForm.processing}>
                            Save changes
                        </Button>
                    </SheetFooter>
                </form>
            </FormDrawer>
        </>
    );
}

AdminDiscountsIndex.layout = (page: React.ReactNode) => (
    <AppLayout
        breadcrumbs={[
            {
                title: 'Discounts & promotions',
                href: '/admin/discounts',
            },
        ]}
    >
        {page}
    </AppLayout>
);

type DiscountForm = ReturnType<typeof useForm<DiscountFormData>>;

function DiscountFormFields({
    form,
    idPrefix,
    packages,
    addons,
    locations,
    customers,
}: {
    form: DiscountForm;
    idPrefix: string;
    packages: PackageOption[];
    addons: AddonOption[];
    locations: LocationOption[];
    customers: CustomerOption[];
}) {
    const { data, setData, errors } = form;
    const id = (name: string) => `${idPrefix}-${name}`;

    const bogoTriggerOptions = data.bogo_trigger_type === 'package' ? packages : addons;
    const bogoRewardOptions = data.bogo_reward_type === 'package' ? packages : addons;

    return (
        <>
            <FormField label="Name" htmlFor={id('name')} error={errors.name}>
                <Input
                    id={id('name')}
                    value={data.name}
                    onChange={(e) => setData('name', e.target.value)}
                />
            </FormField>

            <FormField
                label="Description"
                htmlFor={id('description')}
                error={errors.description}
            >
                <Textarea
                    id={id('description')}
                    rows={2}
                    value={data.description}
                    onChange={(e) => setData('description', e.target.value)}
                />
            </FormField>

            <div className="grid grid-cols-3 gap-3">
                <FormField label="Method" htmlFor={id('method')} error={errors.method}>
                    <NativeSelect
                        id={id('method')}
                        value={data.method}
                        onChange={(e) =>
                            setData('method', e.target.value as DiscountFormData['method'])
                        }
                    >
                        <option value="code">Code</option>
                        <option value="automatic">Automatic</option>
                    </NativeSelect>
                </FormField>

                <FormField label="Applies to" htmlFor={id('class')} error={errors.class}>
                    <NativeSelect
                        id={id('class')}
                        value={data.class}
                        onChange={(e) =>
                            setData('class', e.target.value as DiscountFormData['class'])
                        }
                    >
                        <option value="order">Whole order</option>
                        <option value="service">Specific service</option>
                    </NativeSelect>
                </FormField>

                <FormField label="Type" htmlFor={id('type')} error={errors.type}>
                    <NativeSelect
                        id={id('type')}
                        value={data.type}
                        onChange={(e) =>
                            setData('type', e.target.value as DiscountFormData['type'])
                        }
                    >
                        <option value="percentage">Percentage</option>
                        <option value="fixed_amount">Fixed amount</option>
                        <option value="buy_x_get_y">Buy X, get Y</option>
                    </NativeSelect>
                </FormField>
            </div>

            {data.method === 'code' && (
                <FormField label="Promo code" htmlFor={id('code')} error={errors.code}>
                    <Input
                        id={id('code')}
                        value={data.code}
                        onChange={(e) => setData('code', e.target.value.toUpperCase())}
                        placeholder="SUMMER10"
                    />
                </FormField>
            )}

            {data.type === 'percentage' && (
                <FormField
                    label="Percent off"
                    htmlFor={id('percent_value')}
                    error={errors.percent_value}
                >
                    <Input
                        id={id('percent_value')}
                        type="number"
                        min={0.01}
                        max={100}
                        step="0.01"
                        value={data.percent_value}
                        onChange={(e) =>
                            setData(
                                'percent_value',
                                e.target.value === '' ? '' : Number(e.target.value),
                            )
                        }
                    />
                </FormField>
            )}

            {data.type === 'fixed_amount' && (
                <FormField
                    label="Amount off"
                    htmlFor={id('fixed_amount_cents')}
                    error={errors.fixed_amount_cents}
                >
                    <MoneyInput
                        id={id('fixed_amount_cents')}
                        cents={data.fixed_amount_cents}
                        onCentsChange={(cents) => setData('fixed_amount_cents', cents)}
                    />
                </FormField>
            )}

            {data.type === 'buy_x_get_y' && (
                <div className="grid gap-3 rounded-lg border p-3">
                    <p className="text-sm font-medium">Buy X, get Y</p>
                    <p className="text-xs text-muted-foreground">
                        Quantities above 1 aren&apos;t supported yet — packages and
                        add-ons are boolean present/absent in a booking.
                    </p>
                    <div className="grid grid-cols-2 gap-3">
                        <FormField
                            label="Customer must buy"
                            htmlFor={id('bogo_trigger_type')}
                            error={errors.bogo_trigger_type}
                        >
                            <NativeSelect
                                id={id('bogo_trigger_type')}
                                value={data.bogo_trigger_type}
                                onChange={(e) => {
                                    setData(
                                        'bogo_trigger_type',
                                        e.target.value as DiscountFormData['bogo_trigger_type'],
                                    );
                                    setData('bogo_trigger_id', '');
                                }}
                            >
                                <option value="">Select type...</option>
                                <option value="package">Package</option>
                                <option value="addon">Add-on</option>
                            </NativeSelect>
                        </FormField>
                        <FormField
                            label="Item"
                            htmlFor={id('bogo_trigger_id')}
                            error={errors.bogo_trigger_id}
                        >
                            <NativeSelect
                                id={id('bogo_trigger_id')}
                                value={data.bogo_trigger_id}
                                onChange={(e) =>
                                    setData(
                                        'bogo_trigger_id',
                                        e.target.value === '' ? '' : Number(e.target.value),
                                    )
                                }
                                disabled={!data.bogo_trigger_type}
                            >
                                <option value="">Select item...</option>
                                {bogoTriggerOptions.map((item) => (
                                    <option key={item.id} value={item.id}>
                                        {item.name}
                                    </option>
                                ))}
                            </NativeSelect>
                        </FormField>
                    </div>
                    <div className="grid grid-cols-2 gap-3">
                        <FormField
                            label="Customer gets"
                            htmlFor={id('bogo_reward_type')}
                            error={errors.bogo_reward_type}
                        >
                            <NativeSelect
                                id={id('bogo_reward_type')}
                                value={data.bogo_reward_type}
                                onChange={(e) => {
                                    setData(
                                        'bogo_reward_type',
                                        e.target.value as DiscountFormData['bogo_reward_type'],
                                    );
                                    setData('bogo_reward_id', '');
                                }}
                            >
                                <option value="">Select type...</option>
                                <option value="package">Package</option>
                                <option value="addon">Add-on</option>
                            </NativeSelect>
                        </FormField>
                        <FormField
                            label="Item"
                            htmlFor={id('bogo_reward_id')}
                            error={errors.bogo_reward_id}
                        >
                            <NativeSelect
                                id={id('bogo_reward_id')}
                                value={data.bogo_reward_id}
                                onChange={(e) =>
                                    setData(
                                        'bogo_reward_id',
                                        e.target.value === '' ? '' : Number(e.target.value),
                                    )
                                }
                                disabled={!data.bogo_reward_type}
                            >
                                <option value="">Select item...</option>
                                {bogoRewardOptions.map((item) => (
                                    <option key={item.id} value={item.id}>
                                        {item.name}
                                    </option>
                                ))}
                            </NativeSelect>
                        </FormField>
                    </div>
                    <FormField
                        label="Reward discount %"
                        htmlFor={id('bogo_reward_discount_percent')}
                        error={errors.bogo_reward_discount_percent}
                    >
                        <Input
                            id={id('bogo_reward_discount_percent')}
                            type="number"
                            min={1}
                            max={100}
                            value={data.bogo_reward_discount_percent}
                            onChange={(e) =>
                                setData(
                                    'bogo_reward_discount_percent',
                                    Number(e.target.value),
                                )
                            }
                        />
                    </FormField>
                </div>
            )}

            {data.class === 'service' && (
                <div className="grid gap-3">
                    <FormField label="Restrict to packages" htmlFor={id('package_ids')}>
                        <CheckboxList
                            items={packages}
                            selectedIds={data.package_ids}
                            onChange={(ids) => setData('package_ids', ids)}
                            emptyLabel="No packages configured."
                        />
                    </FormField>
                    <FormField label="Restrict to add-ons" htmlFor={id('addon_ids')}>
                        <CheckboxList
                            items={addons}
                            selectedIds={data.addon_ids}
                            onChange={(ids) => setData('addon_ids', ids)}
                            emptyLabel="No add-ons configured."
                        />
                    </FormField>
                    <p className="text-xs text-muted-foreground">
                        Leave both empty to apply to any package or add-on.
                    </p>
                </div>
            )}

            <FormField label="Restrict to locations" htmlFor={id('location_ids')}>
                <LocationMultiSelect
                    locations={locations}
                    selectedIds={data.location_ids}
                    onChange={(ids) => setData('location_ids', ids)}
                />
            </FormField>

            <FormField label="Restrict to one customer" htmlFor={id('customer_id')}>
                <NativeSelect
                    id={id('customer_id')}
                    value={data.customer_id}
                    onChange={(e) =>
                        setData(
                            'customer_id',
                            e.target.value === '' ? '' : Number(e.target.value),
                        )
                    }
                >
                    <option value="">General use (any customer)</option>
                    {customers.map((customer) => (
                        <option key={customer.id} value={customer.id}>
                            {customer.name} ({customer.email})
                        </option>
                    ))}
                </NativeSelect>
            </FormField>

            <div className="grid grid-cols-2 gap-3">
                <FormField
                    label="Minimum order"
                    htmlFor={id('min_order_amount_cents')}
                    error={errors.min_order_amount_cents}
                >
                    <MoneyInput
                        id={id('min_order_amount_cents')}
                        cents={data.min_order_amount_cents}
                        onCentsChange={(cents) => setData('min_order_amount_cents', cents)}
                    />
                </FormField>
                <FormField
                    label="Max discount cap"
                    htmlFor={id('max_discount_amount_cents')}
                    error={errors.max_discount_amount_cents}
                >
                    <MoneyInput
                        id={id('max_discount_amount_cents')}
                        cents={
                            typeof data.max_discount_amount_cents === 'number'
                                ? data.max_discount_amount_cents
                                : 0
                        }
                        onCentsChange={(cents) =>
                            setData('max_discount_amount_cents', cents)
                        }
                    />
                </FormField>
            </div>

            <div className="grid grid-cols-2 gap-3">
                <FormField
                    label="Total use limit"
                    htmlFor={id('usage_limit_total')}
                    error={errors.usage_limit_total}
                >
                    <Input
                        id={id('usage_limit_total')}
                        type="number"
                        min={1}
                        placeholder="Unlimited"
                        value={data.usage_limit_total}
                        onChange={(e) =>
                            setData(
                                'usage_limit_total',
                                e.target.value === '' ? '' : Number(e.target.value),
                            )
                        }
                    />
                </FormField>
                <FormField
                    label="Per-customer limit"
                    htmlFor={id('usage_limit_per_customer')}
                    error={errors.usage_limit_per_customer}
                >
                    <Input
                        id={id('usage_limit_per_customer')}
                        type="number"
                        min={1}
                        placeholder="Unlimited"
                        value={data.usage_limit_per_customer}
                        onChange={(e) =>
                            setData(
                                'usage_limit_per_customer',
                                e.target.value === '' ? '' : Number(e.target.value),
                            )
                        }
                    />
                </FormField>
            </div>

            <div className="grid grid-cols-2 gap-3">
                <FormField
                    label="Starts"
                    htmlFor={id('starts_at')}
                    error={errors.starts_at}
                >
                    <Input
                        id={id('starts_at')}
                        type="date"
                        value={data.starts_at}
                        onChange={(e) => setData('starts_at', e.target.value)}
                    />
                </FormField>
                <FormField label="Ends" htmlFor={id('ends_at')} error={errors.ends_at}>
                    <Input
                        id={id('ends_at')}
                        type="date"
                        value={data.ends_at}
                        onChange={(e) => setData('ends_at', e.target.value)}
                    />
                </FormField>
            </div>

            <div className="flex items-center gap-2">
                <Switch
                    id={id('is_active')}
                    checked={data.is_active}
                    onCheckedChange={(checked) => setData('is_active', checked)}
                />
                <Label htmlFor={id('is_active')}>Active</Label>
            </div>
        </>
    );
}
