/* The till. Tap products to add them (tap again for more), check the cart, choose how the customer paid, confirm.
   Or "Quick sale": just an amount and a note, for businesses without a product list.
   - Credit: choose who takes the goods (or type a new customer) and when they'll pay: it opens a loan.
   - "Sold earlier?": enter sales after the shift with their real date and time (marked on the sale). Stays on for
     typing in several.
   - No internet: the sale is kept on the phone and sent when the connection is back (resources/js/offline.ts).
   Built for one-handed use on a small phone: big tiles, the total always in view, Charge in thumb reach. */
import { Link, router, usePage } from '@inertiajs/react';
import { useEffect, useMemo, useState, type FormEvent } from 'react';
import { Banknote, Building2, Check, ChevronRight, Clock, CloudOff, HandCoins, History, Minus, Package, Plus, Search, ShoppingCart, Smartphone, Trash2, X, Zap } from 'lucide-react';
import ShopLayout from '../../layouts/ShopLayout';
import ScaleDialog from '../../components/ScaleDialog';
import { Button, Field, Input, Select, cx } from '../../components/ui';
import { money, qty, toMinor, uuid } from '../../lib';
import { submitOrQueue, useOffline } from '../../offline';
import { useT } from '../../i18n';
import type { SharedProps } from '../../types';

type Item = { id: number; name: string; price: number; categoryId: number | null; stock: number | null; isLow: boolean; loose: boolean; unit: string | null };
type Line = { qty: number; price: string | null; worth?: number | null }; // price: typed override (only when allowed); worth: sold by money
type Customer = { id: number; name: string; phone: string | null };
type Props = {
    products: Item[]; categories: { id: number; name: string }[]; customers: Customer[]; methods: Record<string, string>;
    today: { count: number; total: string }; requireShift: boolean; now: string;
    /** the day's money in one amount (kaunjika, barbershops), what was spent today, and the "Spent today" buttons */
    dayTotal: boolean; spentToday: string | null; quickExpenses: { category: string; label: string }[];
};

const METHOD_ICONS: Record<string, typeof Banknote> = { cash: Banknote, airtel_money: Smartphone, tnm_mpamba: Smartphone, bank: Building2, credit: HandCoins };

/** Cash, Airtel Money, Mpamba, Bank, Credit: big buttons, one tap. */
function Methods({ methods, value, onChange, error }: { methods: Record<string, string>; value: string; onChange: (m: string) => void; error?: string }) {
    const t = useT();
    return (
        <div>
            <p className="mb-2 text-sm font-bold text-ink">{t('How did they pay?')}</p>
            <div className="grid grid-cols-2 gap-2" role="radiogroup" aria-label={t('How did they pay?')}>
                {Object.entries(methods).map(([key, label]) => {
                    const Icon = METHOD_ICONS[key] ?? Banknote;
                    const on = value === key;
                    return (
                        <button key={key} type="button" role="radio" aria-checked={on} onClick={() => onChange(key)}
                            className={cx('flex items-center gap-2 rounded-xl border-2 px-3 py-3 text-left text-sm font-bold transition', key === 'credit' && 'col-span-2', on ? 'border-brand bg-brand/[0.06] text-brand' : 'border-line bg-white text-ink-2 hover:border-ink/20')}>
                            <Icon className="size-5 shrink-0" aria-hidden />{t(label)}
                        </button>
                    );
                })}
            </div>
            {error && <p className="mt-1.5 text-sm font-semibold text-rose-600" role="alert">{error}</p>}
        </div>
    );
}

/** Who takes the goods on credit: pick a customer, or type a new one. */
function CreditFields({ customers, value, onChange, errors }: {
    customers: Customer[]; errors: Record<string, string>;
    value: { customer_id: string; new_customer_name: string; new_customer_phone: string; due_on: string };
    onChange: (v: Partial<{ customer_id: string; new_customer_name: string; new_customer_phone: string; due_on: string }>) => void;
}) {
    const t = useT();
    const isNew = value.customer_id === 'new' || customers.length === 0;
    return (
        <div className="space-y-3 rounded-xl bg-amber-50 p-3">
            <Field label={t('Who is taking it on credit?')} error={errors.customer_id}>
                {customers.length > 0 && (
                    <Select value={value.customer_id} onChange={(e) => onChange({ customer_id: e.target.value })}>
                        <option value="">{t('Choose a customer')}</option>
                        {customers.map((c) => <option key={c.id} value={String(c.id)}>{c.name}{c.phone ? ` · ${c.phone}` : ''}</option>)}
                        <option value="new">+ {t('New customer')}</option>
                    </Select>
                )}
            </Field>
            {isNew && (
                <div className="grid grid-cols-2 gap-2">
                    <Input placeholder={t('Customer name')} value={value.new_customer_name} onChange={(e) => onChange({ new_customer_name: e.target.value })} />
                    <Input type="tel" inputMode="tel" placeholder={t('Phone number')} value={value.new_customer_phone} onChange={(e) => onChange({ new_customer_phone: e.target.value })} />
                </div>
            )}
            <Field label={t('Pay by (optional)')} error={errors.due_on}>
                <Input type="date" value={value.due_on} onChange={(e) => onChange({ due_on: e.target.value })} />
            </Field>
        </div>
    );
}

const EMPTY_CREDIT = { customer_id: '', new_customer_name: '', new_customer_phone: '', due_on: '' };

export default function Sell({ products, categories, customers, methods, today, requireShift, now, dayTotal: kaunjika, spentToday, quickExpenses }: Props) {
    const { business, flash, errors, shift } = usePage<SharedProps>().props;
    const t = useT();
    const { online } = useOffline();
    const currency = business?.currency ?? 'MWK';
    const canChangePrice = !!business?.canChangePrice;
    // kaunjika records the day's money, not products
    const [tab, setTab] = useState<'items' | 'quick'>(products.length && !kaunjika ? 'items' : 'quick');
    const [spending, setSpending] = useState<string | null>(null);
    const [spendAmount, setSpendAmount] = useState('');
    const [cart, setCart] = useState<Record<number, Line>>({});
    const [search, setSearch] = useState('');
    const [category, setCategory] = useState<number | null>(null);
    const [sheet, setSheet] = useState(false);
    const [method, setMethod] = useState('cash');
    const [credit, setCredit] = useState(EMPTY_CREDIT);
    const [note, setNote] = useState('');
    const [amount, setAmount] = useState('');
    const [late, setLate] = useState(false);
    const [soldAt, setSoldAt] = useState(now);
    const [busy, setBusy] = useState(false);
    const [opening, setOpening] = useState('');
    // one id per sale attempt: pressing Confirm twice, or a resend, saves the sale once
    const [saleId, setSaleId] = useState(uuid);
    const [done, setDone] = useState<{ number?: number; total: string; method: string; queued?: boolean; late?: boolean } | null>(null);

    const byId = useMemo(() => new Map(products.map((p) => [p.id, p])), [products]);
    const shown = products.filter((p) => (!category || p.categoryId === category) && (!search || p.name.toLowerCase().includes(search.toLowerCase())));
    const lines = Object.entries(cart).map(([id, l]) => ({ product: byId.get(Number(id))!, ...l })).filter((l) => l.product);
    const unitPrice = (l: (typeof lines)[number]) => (l.price !== null ? toMinor(l.price) ?? 0 : l.product.price);
    const lineTotal = (l: (typeof lines)[number]) => (l.worth ? l.worth : Math.round(l.qty * unitPrice(l)));
    const total = lines.reduce((sum, l) => sum + lineTotal(l), 0);
    const count = lines.reduce((sum, l) => sum + l.qty, 0);
    const quickMinor = toMinor(amount);
    // a shift must be open to sell (if the owner wants that), except when typing in earlier sales, or offline
    const needShift = requireShift && !shift && !late && online;

    // loose items (rice by the kg) are weighed: the scale box sets how much
    const [weighing, setWeighing] = useState<Item | null>(null);
    const tapItem = (p: Item) => (p.loose ? setWeighing(p) : add(p));
    const setWeighed = (p: Item, quantity: number, worth: number | null) => { setCart((c) => ({ ...c, [p.id]: { qty: quantity, price: c[p.id]?.price ?? null, worth } })); setWeighing(null); };
    const add = (p: Item, by = 1) => setCart((c) => {
        const next = Math.round(((c[p.id]?.qty ?? 0) + by) * 100) / 100;
        if (next <= 0) { const { [p.id]: _gone, ...rest } = c; void _gone; return rest; }
        return { ...c, [p.id]: { qty: next, price: c[p.id]?.price ?? null } };
    });
    const setLine = (id: number, patch: Partial<Line>) => setCart((c) => ({ ...c, [id]: { ...c[id], ...patch } }));
    const remove = (id: number) => setCart((c) => { const { [id]: _gone, ...rest } = c; void _gone; return rest; });

    // the success tick, from the server's answer
    useEffect(() => {
        if (!flash?.sale) return;
        setDone(flash.sale);
    }, [flash?.sale]);
    useEffect(() => {
        if (!done) return;
        const timer = setTimeout(() => setDone(null), 2800);
        return () => clearTimeout(timer);
    }, [done]);

    const openShift = () => router.post(route('shifts.open'), { opening_cash: opening || '0' }, { preserveScroll: true, preserveState: true });
    const shiftGate = (compact: boolean) => (
        <div className={cx('rounded-card border-2 border-brand/30 bg-white p-4', !compact && 'mb-4 shadow-card')}>
            <p className="flex items-center gap-2 text-base font-extrabold text-ink">
                <Clock className="size-5 text-brand" aria-hidden />{compact ? t('Open your shift to finish this sale') : t('Open your shift to start selling')}
            </p>
            <Field label={t('Cash in the till now')} error={errors.opening_minor ?? errors.opening_cash} className="mt-3">
                <div className="flex gap-2">
                    <Input inputMode="decimal" placeholder="0" value={opening} onChange={(e) => setOpening(e.target.value)}
                        onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); openShift(); } }} className="flex-1" />
                    <Button type="button" onClick={openShift}>{t('Open shift')}</Button>
                </div>
            </Field>
        </div>
    );

    const reset = () => { setCart({}); setNote(''); setAmount(''); setMethod('cash'); setCredit(EMPTY_CREDIT); setSheet(false); setSaleId(uuid()); };

    /** Kaunjika: money spent today (food, transport, market fee), two taps. Works offline too. */
    const spend = (e: FormEvent) => {
        e.preventDefault();
        if (!spending || !toMinor(spendAmount)) return;
        submitOrQueue({
            url: route('expenses.store'), type: 'expense', label: `${spending} ${spendAmount}`,
            data: { client_uuid: uuid(), amount: spendAmount, category: spending, payment_method: 'cash', spent_on: now.slice(0, 10) },
            onSuccess: () => { setSpending(null); setSpendAmount(''); }, onQueued: () => { setSpending(null); setSpendAmount(''); },
        });
    };

    const confirm = (e?: FormEvent) => {
        e?.preventDefault();
        if (busy) return;
        const isCredit = method === 'credit';
        const payload: Record<string, unknown> = {
            client_uuid: saleId, kind: tab, payment_method: method, note: note || null,
            ...(tab === 'items'
                ? { items: lines.map((l) => ({ product_id: l.product.id, quantity: l.qty, ...(l.price !== null ? { unit_price: toMinor(l.price) ?? 0 } : {}), ...(l.worth ? { amount: l.worth } : {}) })) }
                : { amount, ...(kaunjika ? { payment_method: 'cash', note: t("Day's takings") } : {}) }),
            ...(isCredit ? { customer_id: credit.customer_id && credit.customer_id !== 'new' ? Number(credit.customer_id) : null, new_customer_name: credit.new_customer_name || null, new_customer_phone: credit.new_customer_phone || null, due_on: credit.due_on || null } : {}),
            ...(late ? { entered_late: true, sold_at: soldAt } : {}),
        };
        const totalLabel = money(tab === 'items' ? total : quickMinor ?? 0, currency);
        setBusy(true);
        submitOrQueue({
            url: route('sales.store'), type: 'sale', data: payload,
            label: `${tab === 'items' ? lines.map((l) => `${qty(l.qty)} × ${l.product.name}`).join(', ') : note || t('Quick sale')} · ${totalLabel}`,
            onSuccess: reset,
            onQueued: () => { setDone({ total: totalLabel, method: t(methods[method] ?? method), queued: true }); reset(); },
            onFinish: () => setBusy(false),
        });
    };

    const creditBlock = method === 'credit' && <CreditFields customers={customers} value={credit} onChange={(v) => setCredit((c) => ({ ...c, ...v }))} errors={errors} />;
    const lateBlock = late && (
        <Field label={t('When was it sold?')} error={errors.sold_at}>
            <Input type="datetime-local" value={soldAt} max={now} onChange={(e) => setSoldAt(e.target.value)} />
        </Field>
    );

    const cartPanel = (
        <div className="flex h-full flex-col">
            {lines.length === 0 ? (
                <div className="grid flex-1 place-items-center py-10 text-center text-sm text-muted">
                    <div><ShoppingCart className="mx-auto mb-2 size-8 text-line" aria-hidden />{t('Tap products to add them.')}</div>
                </div>
            ) : (
                <ul className="divide-y divide-line">
                    {lines.map((l) => (
                        <li key={l.product.id} className="py-3">
                            <div className="flex items-start gap-2">
                                <p className="min-w-0 flex-1 text-[15px] leading-snug font-bold text-ink">{l.product.name}</p>
                                <p className="shrink-0 text-[15px] font-extrabold text-ink">{money(lineTotal(l), currency)}</p>
                            </div>
                            <div className="mt-2 flex items-center gap-2">
                                {l.product.loose ? (
                                    <button type="button" onClick={() => setWeighing(l.product)} className="flex h-10 items-center gap-1.5 rounded-xl border border-line px-3 text-base font-bold text-ink">
                                        {qty(l.qty)} {l.product.unit}<span className="text-xs font-semibold text-brand">{t('change')}</span>
                                    </button>
                                ) : (
                                <div className="flex items-center rounded-xl border border-line">
                                    <button type="button" onClick={() => add(l.product, -1)} className="grid size-10 place-items-center text-ink-2" aria-label={`One less ${l.product.name}`}><Minus className="size-4" /></button>
                                    <input inputMode="decimal" value={qty(l.qty)} onChange={(e) => { const n = Number(e.target.value.replace(',', '.')); if (!Number.isNaN(n) && n >= 0) setLine(l.product.id, { qty: n, worth: null }); }}
                                        onBlur={() => l.qty <= 0 && remove(l.product.id)} className="w-12 text-center text-base font-bold text-ink focus:outline-none" aria-label={`Quantity of ${l.product.name}`} />
                                    <button type="button" onClick={() => add(l.product)} className="grid size-10 place-items-center text-ink-2" aria-label={`One more ${l.product.name}`}><Plus className="size-4" /></button>
                                </div>
                                )}
                                {canChangePrice ? (
                                    <label className="flex min-w-0 flex-1 items-center gap-1 text-xs text-muted">
                                        @<input inputMode="decimal" value={l.price ?? String(l.product.price / 100)} onChange={(e) => setLine(l.product.id, { price: e.target.value })}
                                            className={cx('w-full min-w-0 rounded-lg border px-2 py-2 text-sm text-ink focus:border-brand focus:outline-none', l.price !== null && toMinor(l.price) !== l.product.price ? 'border-amber-400 bg-amber-50' : 'border-line')} aria-label={`Price of ${l.product.name}`} />
                                    </label>
                                ) : <span className="flex-1 text-xs text-muted">@ {money(l.product.price, currency)}{l.product.loose ? `/${l.product.unit}` : ''}</span>}
                                <button type="button" onClick={() => remove(l.product.id)} className="grid size-10 place-items-center rounded-xl text-muted hover:bg-rose-50 hover:text-rose-600" aria-label={`Remove ${l.product.name}`}><Trash2 className="size-4" /></button>
                            </div>
                            {l.product.stock !== null && l.qty > l.product.stock && (
                                <p className="mt-1 text-xs font-semibold text-amber-700">Only {qty(Math.max(0, l.product.stock))}{l.product.loose ? ` ${l.product.unit}` : ''} in stock. You can still sell; fix the count on Products.</p>
                            )}
                        </li>
                    ))}
                </ul>
            )}
            {lines.length > 0 && (
                <form onSubmit={confirm} className="mt-auto space-y-4 border-t border-line pt-4">
                    <div className="flex items-baseline justify-between">
                        <span className="text-sm font-semibold text-muted">{t('Total')} · {qty(count)}</span>
                        <span className="text-3xl font-extrabold tracking-tight text-ink">{money(total, currency)}</span>
                    </div>
                    <Methods methods={methods} value={method} onChange={setMethod} error={errors.payment_method} />
                    {creditBlock}
                    {lateBlock}
                    <Input placeholder={t('Note (optional)')} value={note} onChange={(e) => setNote(e.target.value)} maxLength={255} />
                    {(errors.items || errors.shift || Object.keys(errors).some((k) => k.startsWith('items.'))) && (
                        <p className="text-sm font-semibold text-rose-600" role="alert">{errors.shift ?? errors.items ?? Object.entries(errors).find(([k]) => k.startsWith('items.'))?.[1]}</p>
                    )}
                    {needShift ? shiftGate(true) : (
                        <Button type="submit" size="lg" className="w-full !py-4 text-lg" icon={Check} disabled={busy}>{busy ? t('Saving…') : `${t('Confirm sale')} · ${money(total, currency)}`}</Button>
                    )}
                    <button type="button" onClick={() => { setCart({}); setSheet(false); }} className="w-full text-center text-sm font-semibold text-muted hover:text-rose-600">{t('Clear the cart')}</button>
                </form>
            )}
        </div>
    );

    return (
        <ShopLayout title="Sell" wide>
            {/* today, at a glance */}
            <Link href={route('sales.index')} className="mb-3 flex items-center gap-2 rounded-xl bg-white px-3 py-2.5 text-sm shadow-card ring-1 ring-line">
                <span className="text-muted">{t('Today')}</span>
                <span className="font-bold text-ink">{today.total}</span>
                <span className="text-muted">· {today.count}</span>
                <ChevronRight className="ml-auto size-4 text-muted" aria-hidden />
            </Link>

            {needShift && shiftGate(false)}

            {/* kaunjika: the day's costs (food, transport, market fee) in two taps */}
            {kaunjika && (
                <div className="mb-3 rounded-xl bg-white px-3 py-2.5 shadow-card ring-1 ring-line">
                    <div className="flex items-center justify-between gap-2 text-sm">
                        <span className="text-muted">{t('Spent today')}</span>
                        <span className="font-bold text-ink">{spentToday}</span>
                    </div>
                    <div className="mt-2 flex flex-wrap gap-1.5">
                        {quickExpenses.map(({ category: k, label }) => (
                            <button key={k} type="button" onClick={() => { setSpending(k); setSpendAmount(''); }} className={cx('rounded-full px-3 py-1.5 text-xs font-bold', spending === k ? 'bg-ink text-white' : 'bg-line-2 text-ink-2')}>+ {t(label)}</button>
                        ))}
                    </div>
                    {spending && (
                        <form onSubmit={spend} className="mt-2 flex gap-2">
                            <Input inputMode="decimal" placeholder={t('Amount')} value={spendAmount} onChange={(e) => setSpendAmount(e.target.value)} className="flex-1" autoFocus />
                            <Button type="submit" disabled={!toMinor(spendAmount)}>{t('Save')}</Button>
                        </form>
                    )}
                </div>
            )}

            {/* kaunjika with no product list: just the price buttons, no Products tab */}
            {!(kaunjika && products.length === 0) && (
            <div className="mb-3 grid grid-cols-2 rounded-xl bg-line-2 p-1" role="tablist">
                {(['items', 'quick'] as const).map((k) => (
                    <button key={k} role="tab" aria-selected={tab === k} onClick={() => setTab(k)}
                        className={cx('flex items-center justify-center gap-1.5 rounded-lg py-2.5 text-sm font-bold transition', tab === k ? 'bg-white text-ink shadow-card' : 'text-muted')}>
                        {k === 'items' ? <><Package className="size-4" aria-hidden />{t('Products')}</> : <><Zap className="size-4" aria-hidden />{t('Quick sale')}</>}
                    </button>
                ))}
            </div>
            )}

            <button onClick={() => setLate((l) => !l)} className={cx('mb-4 flex w-full items-center gap-2 rounded-xl px-3 py-2 text-left text-sm font-semibold', late ? 'bg-amber-100 text-amber-900' : 'text-muted hover:bg-line-2')}>
                <History className="size-4 shrink-0" aria-hidden />
                <span className="flex-1">{late ? t('Entered after the shift') : t('Sold earlier? Enter the date and time')}</span>
                {late && <X className="size-4" aria-hidden />}
            </button>

            {tab === 'items' ? (
                <div className="lg:grid lg:grid-cols-[minmax(0,1fr)_380px] lg:gap-6">
                    <div>
                        {products.length > 8 && (
                            <div className="relative mb-3">
                                <Search className="pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted" aria-hidden />
                                <Input type="search" placeholder={t('Find a product')} value={search} onChange={(e) => setSearch(e.target.value)} className="pl-9" />
                            </div>
                        )}
                        {categories.length > 0 && (
                            <div className="no-scrollbar -mx-4 mb-3 flex gap-2 overflow-x-auto px-4">
                                {[{ id: null as number | null, name: t('All') }, ...categories].map((c) => (
                                    <button key={c.id ?? 'all'} onClick={() => setCategory(c.id)}
                                        className={cx('shrink-0 rounded-full px-4 py-2 text-sm font-bold', category === c.id ? 'bg-ink text-white' : 'bg-white text-ink-2 ring-1 ring-line')}>
                                        {c.name}
                                    </button>
                                ))}
                            </div>
                        )}

                        {products.length === 0 ? (
                            <div className="rounded-card border border-dashed border-line bg-white p-6 text-center">
                                <Package className="mx-auto size-8 text-muted" aria-hidden />
                                <p className="mt-2 font-bold text-ink">{t('No products yet')}</p>
                                <p className="mt-1 text-sm text-muted">{t('Use Quick sale, or add your products first.')}</p>
                                <Link href={route('products.index')} className="mt-3 inline-block text-sm font-bold text-brand">{t('Go to Products')}</Link>
                            </div>
                        ) : (
                            <div className="grid grid-cols-2 gap-2.5 sm:grid-cols-3 xl:grid-cols-4">
                                {shown.map((p) => {
                                    const inCart = cart[p.id]?.qty;
                                    const out = p.stock !== null && p.stock <= 0;
                                    return (
                                        <button key={p.id} onClick={() => tapItem(p)}
                                            className={cx('relative flex min-h-24 flex-col justify-between rounded-2xl border-2 bg-white p-3 text-left shadow-card transition active:scale-[0.97]', inCart ? 'border-brand' : 'border-transparent ring-1 ring-line')}>
                                            {inCart && <span className="absolute -top-2 -right-2 grid min-w-7 place-items-center rounded-full bg-brand px-1.5 py-0.5 text-sm font-extrabold text-white shadow">{qty(inCart)}</span>}
                                            <span className="line-clamp-2 text-[15px] leading-snug font-bold text-ink">{p.name}</span>
                                            <span className="mt-2 flex items-end justify-between gap-1">
                                                <span className="text-base font-extrabold text-ink">{money(p.price, currency)}{p.loose && <span className="text-xs font-semibold text-muted">/{p.unit}</span>}</span>
                                                {p.stock !== null && (
                                                    <span className={cx('text-xs font-bold', out ? 'text-rose-600' : p.isLow ? 'text-amber-600' : 'text-muted')}>{out ? t('Out') : `${qty(p.stock)}${p.loose ? ` ${p.unit}` : ''}`}</span>
                                                )}
                                            </span>
                                        </button>
                                    );
                                })}
                                {shown.length === 0 && <p className="col-span-full py-8 text-center text-sm text-muted">Nothing matches “{search}”.</p>}
                            </div>
                        )}
                    </div>

                    {/* computers: the cart beside the products */}
                    <aside className="hidden lg:block">
                        <div className="sticky top-20 flex max-h-[calc(100vh-6rem)] flex-col overflow-y-auto rounded-card border border-line bg-white p-4 shadow-card">
                            <p className="mb-1 text-sm font-bold text-muted">{t('Cart')}</p>
                            {cartPanel}
                        </div>
                    </aside>
                </div>
            ) : (
                <form onSubmit={confirm} className="mx-auto max-w-md space-y-5 rounded-card border border-line bg-white p-4 shadow-card sm:p-6">
                    <div>
                        <label htmlFor="amount" className="mb-2 block text-sm font-bold text-ink">
                            {kaunjika ? (late ? t('Money made that day') : t('Money made today')) : t('Amount')}
                        </label>
                        {kaunjika && <p className="-mt-1 mb-2 text-sm text-muted">{t('Count the money at the end of the day and type the total.')}</p>}
                        <div className="flex items-center gap-2 rounded-2xl border-2 border-line px-4 focus-within:border-brand">
                            <span className="text-lg font-bold text-muted">{currency}</span>
                            <input id="amount" inputMode="decimal" autoComplete="off" placeholder="0" value={amount} onChange={(e) => setAmount(e.target.value)}
                                className="w-full min-w-0 bg-transparent py-4 text-4xl font-extrabold tracking-tight text-ink focus:outline-none" />
                        </div>
                        {errors.amount_minor && <p className="mt-1.5 text-sm font-semibold text-rose-600" role="alert">{errors.amount_minor}</p>}
                    </div>
                    {/* kaunjika: just the day's money (saved as cash); others: what was sold and how it was paid */}
                    {!kaunjika && <Input placeholder={t('What was sold? (optional)')} value={note} onChange={(e) => setNote(e.target.value)} maxLength={255} />}
                    {!kaunjika && <Methods methods={methods} value={method} onChange={setMethod} error={errors.payment_method} />}
                    {!kaunjika && creditBlock}
                    {lateBlock}
                    {errors.shift && <p className="text-sm font-semibold text-rose-600" role="alert">{errors.shift}</p>}
                    {needShift ? shiftGate(true) : (
                        <Button type="submit" size="lg" className="w-full !py-5 text-xl" icon={Check} disabled={busy || !quickMinor}>
                            {busy ? t('Saving…') : kaunjika
                                ? (quickMinor ? `${t('Save')} · ${money(quickMinor, currency)}` : t('Save'))
                                : (quickMinor ? `${t('Confirm sale')} · ${money(quickMinor, currency)}` : t('Confirm sale'))}
                        </Button>
                    )}
                </form>
            )}

            {/* phones: the running total and Charge, above the tab bar */}
            {tab === 'items' && lines.length > 0 && !sheet && (
                <div className="fixed inset-x-0 bottom-[68px] z-20 px-3 pb-2 md:bottom-4 lg:hidden">
                    <button onClick={() => setSheet(true)} className="mx-auto flex w-full max-w-xl items-center gap-3 rounded-2xl bg-ink px-4 py-3.5 text-left text-white shadow-pop active:scale-[0.99]">
                        <span className="grid size-9 place-items-center rounded-full bg-white/15 text-sm font-extrabold">{qty(count)}</span>
                        <span className="flex-1 text-xl font-extrabold tracking-tight">{money(total, currency)}</span>
                        <span className="rounded-xl bg-brand px-4 py-2 text-base font-extrabold">{t('Charge')}</span>
                    </button>
                </div>
            )}
            {sheet && (
                <div className="fixed inset-0 z-40 flex items-end bg-ink/40 lg:hidden" onClick={() => setSheet(false)}>
                    <div className="animate-sheet-in pb-safe flex max-h-[92vh] w-full flex-col overflow-y-auto rounded-t-3xl bg-white px-4 pt-3 pb-4" onClick={(e) => e.stopPropagation()} role="dialog" aria-label={t('Cart')}>
                        <div className="mb-1 flex items-center justify-between">
                            <p className="text-lg font-extrabold text-ink">{t('Cart')}</p>
                            <button onClick={() => setSheet(false)} className="grid size-10 place-items-center rounded-full text-muted hover:bg-line-2" aria-label={t('Back')}><X className="size-5" /></button>
                        </div>
                        {cartPanel}
                    </div>
                </div>
            )}

            {/* sale saved (or kept on the phone) */}
            <ScaleDialog key={weighing?.id ?? 'none'} item={weighing} current={weighing ? cart[weighing.id]?.qty ?? null : null} currency={currency}
                onAdd={(quantity, worth) => weighing && setWeighed(weighing, quantity, worth)} onClose={() => setWeighing(null)} />

            {done && (
                <div className="pointer-events-none fixed inset-0 z-50 grid place-items-center p-6">
                    <div className="animate-pop-in rounded-3xl bg-white px-8 py-6 text-center shadow-pop ring-1 ring-line" role="status">
                        <span className={cx('mx-auto grid size-14 place-items-center rounded-full text-white', done.queued ? 'bg-ink' : 'bg-emerald-500')}>
                            {done.queued ? <CloudOff className="size-7" aria-hidden /> : <Check className="size-8" strokeWidth={3} aria-hidden />}
                        </span>
                        <p className="mt-3 text-sm font-semibold text-muted">{done.queued ? t('Saved on this phone') : `${t('Sale saved')} · #${done.number}`}</p>
                        <p className="text-3xl font-extrabold tracking-tight text-ink">{done.total}</p>
                        <p className="text-sm text-muted">{done.method}</p>
                        {done.queued && <p className="mt-1 max-w-56 text-xs text-muted">{t('It will be sent when the internet is back.')}</p>}
                    </div>
                </div>
            )}
        </ShopLayout>
    );
}
