import { router, useForm } from '@inertiajs/react';
import { Archive, ArchiveRestore } from 'lucide-react';
import { useState } from 'react';
import { Reveal } from '@/components/motion';
import { MoneyInput, PercentInput, QtyInput } from '@/components/NumberInputs';
import { PageHeader } from '@/components/PageHeader';
import { RichTextEditor } from '@/components/RichTextEditor';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardBody, CardHeader } from '@/components/ui/card';
import { Input, Select } from '@/components/ui/input';
import { Field, Label } from '@/components/ui/label';
import AppLayout from '@/layouts/AppLayout';
import { money } from '@/lib/format';
import { BLOCK_META, defaultContent, StructuredBlockEditor, StylePanel, STRUCTURED_TYPES, type BlockContent, type BlockStyle, type StructuredType } from '@/components/quote/BlockEditors';
import { ImageBlock, type ImageSize, type Line } from '@/components/quote/LinesEditor';

type Interval = 'week' | 'month' | 'year' | null;
type ItemType = 'price' | 'text' | 'image' | StructuredType;
type ItemData = {
    id: number | null; type: ItemType; code: string; heading: string; description: string;
    image_path: string | null; image_url: string | null; image_alt: string; image_size: ImageSize; content: BlockContent | null; style: BlockStyle | null;
    unit_price_cents: number; default_qty: string; tax_rate_bp: number; cost_cents: number | null; markup_bp: number | null; discount_bp: number;
    subscription_interval: Interval; subscription_every: number | null; subscription_term: number | null; archived: boolean;
};

/** markup = profit / cost; margin = profit / price. */
const marginFromMarkup = (m: number) => Math.round((m / (10000 + m)) * 10000);
const markupFromMargin = (g: number) => (g >= 10000 ? 0 : Math.round((g / (10000 - g)) * 10000));

export default function ItemEdit({ item, company, canEdit }: {
    item: ItemData; company: { id: number; name: string; default_tax_rate_bp: number; default_markup_bp: number }; canEdit: boolean;
}) {
    const { archived, ...initial } = item;
    const form = useForm(initial);
    const d = form.data;
    const [basis, setBasis] = useState<'markup' | 'margin'>('markup');
    const isNew = item.id === null;
    const isPrice = d.type === 'price';
    const isImage = d.type === 'image';
    const isBlock = (STRUCTURED_TYPES as readonly string[]).includes(d.type);
    const typeLabel = isPrice ? 'Price item' : d.type === 'text' ? 'Text item' : isImage ? 'Image' : BLOCK_META[d.type as StructuredType].label;
    const err = form.errors as Record<string, string>;
    const markup = d.markup_bp ?? company.default_markup_bp;

    const priceFromCost = (cost: number | null, mk: number) => (cost === null ? {} : { unit_price_cents: Math.round(cost * (1 + mk / 10000)) });
    const profit = d.cost_cents !== null ? d.unit_price_cents - d.cost_cents : null;

    const submit = (e: React.FormEvent) => {
        e.preventDefault();
        if (isNew) form.post('/items'); else form.put(`/items/${item.id}`, { preserveScroll: true });
    };
    const title = d.heading || (isNew ? `New ${typeLabel.toLowerCase()}` : 'Untitled item');

    return (
        <AppLayout title={title}>
            <form onSubmit={submit} noValidate>
                <fieldset disabled={!canEdit}>
                    <PageHeader title={title} breadcrumbs={[{ label: 'Item library', href: '/items' }, { label: title }]}
                        description={<span className="inline-flex items-center gap-2">{typeLabel} · {company.name}{archived && <Badge className="bg-stone-100 text-stone-700">Archived</Badge>}</span>}
                        actions={canEdit && <>
                            {!isNew && (
                                <Button type="button" variant="secondary" onClick={() => router.post(`/items/${item.id}/archive`, {}, { preserveScroll: true })}>
                                    {archived ? <><ArchiveRestore className="h-4 w-4" /> Restore</> : <><Archive className="h-4 w-4" /> Archive</>}
                                </Button>
                            )}
                            {!isNew && <Button type="button" variant="danger" onClick={() => confirm('Delete this item? Quotes that already use it keep their copy.') && router.delete(`/items/${item.id}`)}>Delete</Button>}
                            <Button type="submit" disabled={form.processing} data-testid="save-item">{form.processing ? 'Saving…' : isNew ? 'Add item' : 'Save item'}</Button>
                        </>} />

                    <div className="grid gap-6 lg:grid-cols-3">
                        <div className="space-y-6 lg:col-span-2">
                            <Card>
                                <CardHeader title="Details" description={canEdit ? undefined : 'You have read-only access to the item library.'} />
                                <CardBody className="grid gap-4 sm:grid-cols-3">
                                    <Field label="Item code" htmlFor="code" error={form.errors.code} hint="Used for lookup and matching.">
                                        <Input id="code" value={d.code} onChange={(e) => form.setData('code', e.target.value)} />
                                    </Field>
                                    {!isBlock && (
                                        <Field label={isImage ? 'Name / caption' : 'Heading'} htmlFor="heading" error={form.errors.heading} className="sm:col-span-2"
                                            hint={isImage ? 'How you find it in the library search.' : undefined}>
                                            <Input id="heading" value={d.heading} onChange={(e) => form.setData('heading', e.target.value)} />
                                        </Field>
                                    )}
                                    {isBlock && <p className="self-end pb-2 text-xs text-ink-muted sm:col-span-2">The block's heading (below) is how you find it in the library search.</p>}
                                    {(isPrice || d.type === 'text') && (
                                        <div className="sm:col-span-3">
                                            <Label>Description</Label>
                                            <RichTextEditor label="Description" value={d.description} onChange={(h) => form.setData('description', h)} disabled={!canEdit} />
                                        </div>
                                    )}
                                </CardBody>
                            </Card>

                            {isImage && (
                                <Card data-testid="item-image">
                                    <CardHeader title="Image" description="Inserted into quotes as an image block." />
                                    <CardBody>
                                        <ImageBlock line={{ key: 'item', type: 'image', heading: d.heading, image_path: d.image_path, image_url: d.image_url, image_alt: d.image_alt, image_size: d.image_size } as unknown as Line}
                                            onChange={(p) => form.setData({ ...d, ...(p.image_path !== undefined ? { image_path: p.image_path ?? null } : {}), ...(p.image_url !== undefined ? { image_url: p.image_url ?? null } : {}),
                                                ...(p.image_alt !== undefined ? { image_alt: p.image_alt ?? '' } : {}), ...(p.image_size !== undefined ? { image_size: (p.image_size ?? 'full') as ImageSize } : {}) })}
                                            error={err.image_path} />
                                    </CardBody>
                                </Card>
                            )}
                            {isBlock && (
                                <Card data-testid="item-block">
                                    <CardHeader title={BLOCK_META[d.type as StructuredType].label} description={BLOCK_META[d.type as StructuredType].hint} />
                                    <CardBody className="space-y-4">
                                        <StructuredBlockEditor type={d.type as StructuredType} id="item" heading={d.heading} description={d.description}
                                            content={d.content ?? {}} onChange={(p) => form.setData({ ...d, ...(p.heading !== undefined ? { heading: p.heading ?? '' } : {}),
                                                ...(p.description !== undefined ? { description: p.description ?? '' } : {}), ...(p.content !== undefined ? { content: p.content } : {}) })}
                                            errors={Object.entries(err).filter(([k]) => k.startsWith('content')).map(([, v]) => v)} />
                                    </CardBody>
                                </Card>
                            )}
                            {!isPrice && (
                                <Card>
                                    <CardHeader title="Style" description="Spacing, alignment and colours when this is added to a proposal." />
                                    <CardBody><StylePanel id="item" style={d.style} onChange={(s) => form.setData('style', s)} /></CardBody>
                                </Card>
                            )}

                            <Reveal show={isPrice}>
                                <Card>
                                    <CardHeader title="Pricing" />
                                    <CardBody className="grid gap-4 sm:grid-cols-4">
                                        <Field label="Unit price (ex GST)" htmlFor="unit_price" error={form.errors.unit_price_cents}>
                                            <MoneyInput id="unit_price" cents={d.unit_price_cents} onChange={(c) => form.setData('unit_price_cents', c ?? 0)} />
                                        </Field>
                                        <Field label="Default qty" htmlFor="default_qty" error={form.errors.default_qty}>
                                            <QtyInput id="default_qty" value={d.default_qty} onChange={(v) => form.setData('default_qty', v)} />
                                        </Field>
                                        <Field label="Tax" htmlFor="tax">
                                            <Select id="tax" value={d.tax_rate_bp === 1000 ? '1000' : d.tax_rate_bp === 0 ? '0' : 'custom'}
                                                onChange={(e) => form.setData('tax_rate_bp', e.target.value === 'custom' ? 1500 : Number(e.target.value))}>
                                                <option value="1000">GST 10%</option>
                                                <option value="0">GST-free</option>
                                                <option value="custom">Other rate</option>
                                            </Select>
                                        </Field>
                                        <Field label="Default discount" htmlFor="discount">
                                            <PercentInput id="discount" bp={d.discount_bp} onChange={(bp) => form.setData('discount_bp', bp)} />
                                        </Field>
                                        <Reveal show={d.tax_rate_bp !== 1000 && d.tax_rate_bp !== 0}>
                                            <Field label="Tax rate" htmlFor="taxrate">
                                                <PercentInput id="taxrate" bp={d.tax_rate_bp} onChange={(bp) => form.setData('tax_rate_bp', bp)} />
                                            </Field>
                                        </Reveal>
                                    </CardBody>
                                </Card>
                            </Reveal>

                            <Reveal show={isPrice}>
                                <Card>
                                    <CardHeader title="Billing" description="One-off, or a subscription that repeats." />
                                    <CardBody className="grid gap-4 sm:grid-cols-3">
                                        <Field label="Repeats" htmlFor="interval">
                                            <Select id="interval" value={d.subscription_interval ?? ''} onChange={(e) => {
                                                const v = (e.target.value || null) as Interval;
                                                form.setData({ ...d, subscription_interval: v, subscription_every: v ? d.subscription_every || 1 : null, subscription_term: v ? d.subscription_term : null });
                                            }}>
                                                <option value="">One-off</option>
                                                <option value="week">Weekly</option>
                                                <option value="month">Monthly</option>
                                                <option value="year">Yearly</option>
                                            </Select>
                                        </Field>
                                        <Reveal show={!!d.subscription_interval} className="sm:col-span-2" innerClassName="grid gap-4 sm:grid-cols-2">
                                            <Field label={`Every N ${d.subscription_interval ?? 'month'}s`} htmlFor="every">
                                                <Input id="every" type="number" min={1} max={52} value={d.subscription_every ?? 1}
                                                    onChange={(e) => form.setData('subscription_every', Math.max(1, Number(e.target.value) || 1))} />
                                            </Field>
                                            <Field label="For how many periods" htmlFor="term" hint="Leave blank for ongoing.">
                                                <Input id="term" type="number" min={1} max={999} value={d.subscription_term ?? ''}
                                                    onChange={(e) => form.setData('subscription_term', Number(e.target.value) || null)} />
                                            </Field>
                                        </Reveal>
                                    </CardBody>
                                </Card>
                            </Reveal>
                        </div>

                        <aside className="space-y-6">
                            {isNew && (
                                <Card>
                                    <CardHeader title="Item type" />
                                    <CardBody>
                                        <Select aria-label="Item type" value={d.type} onChange={(e) => {
                                            const t = e.target.value as ItemType;
                                            form.setData({ ...d, type: t, content: (STRUCTURED_TYPES as readonly string[]).includes(t) ? (t === d.type ? d.content : defaultContent(t as StructuredType)) : null });
                                        }}>
                                            <option value="price">Price item</option>
                                            <option value="text">Text item (intro, scope, T&amp;Cs)</option>
                                            <option value="image">Image</option>
                                            <optgroup label="Blocks">
                                                {STRUCTURED_TYPES.map((t) => <option key={t} value={t}>{BLOCK_META[t].label}</option>)}
                                            </optgroup>
                                        </Select>
                                    </CardBody>
                                </Card>
                            )}
                            <Reveal show={isPrice && canEdit}>
                                <Card className="lg:sticky lg:top-20">
                                    <CardHeader title="Cost &amp; margin" description="Staff only. Never shown to clients." />
                                    <CardBody className="space-y-4">
                                        <Field label="Cost price" htmlFor="cost">
                                            <MoneyInput id="cost" allowNegative={false} cents={d.cost_cents}
                                                onChange={(c) => form.setData({ ...d, cost_cents: c, ...priceFromCost(c, markup) })} />
                                        </Field>
                                        <div className="flex gap-1 rounded-[5px] bg-stone-100 p-1 text-sm" role="radiogroup" aria-label="Price from">
                                            {(['markup', 'margin'] as const).map((b) => (
                                                <button key={b} type="button" role="radio" aria-checked={basis === b} onClick={() => setBasis(b)}
                                                    className={`flex-1 rounded px-2 py-1 font-medium ${basis === b ? 'bg-surface text-ink shadow-sm' : 'text-ink-muted'}`}>
                                                    {b === 'markup' ? 'Markup' : 'Margin'}
                                                </button>
                                            ))}
                                        </div>
                                        {basis === 'markup' ? (
                                            <Field label="Markup" htmlFor="markup" hint={`Company default ${company.default_markup_bp / 100}%. Sets the price from cost.`}>
                                                <PercentInput id="markup" max={10000} bp={markup}
                                                    onChange={(bp) => form.setData({ ...d, markup_bp: bp, ...priceFromCost(d.cost_cents, bp) })} />
                                            </Field>
                                        ) : (
                                            <Field label="Margin" htmlFor="margin" hint="Profit as a share of the price. Sets the price from cost.">
                                                <PercentInput id="margin" max={99} bp={marginFromMarkup(markup)}
                                                    onChange={(bp) => { const mk = markupFromMargin(bp); form.setData({ ...d, markup_bp: mk, ...priceFromCost(d.cost_cents, mk) }); }} />
                                            </Field>
                                        )}
                                        <dl className="grid grid-cols-2 gap-2 border-t border-line pt-3 text-sm">
                                            <dt className="text-ink-muted">Profit per unit</dt><dd className="text-right tabular-nums">{profit === null ? '—' : money(profit)}</dd>
                                            <dt className="text-ink-muted">Margin</dt>
                                            <dd className="text-right tabular-nums" data-testid="item-margin">{profit === null || !d.unit_price_cents ? '—' : `${((profit / d.unit_price_cents) * 100).toFixed(1)}%`}</dd>
                                        </dl>
                                    </CardBody>
                                </Card>
                            </Reveal>
                        </aside>
                    </div>
                </fieldset>
            </form>
        </AppLayout>
    );
}
