/* Money spent running the business, month by month. Recording works offline too. */
import { router, usePage } from '@inertiajs/react';
import { useState, type FormEvent } from 'react';
import { ChevronLeft, ChevronRight, Plus, Trash2, Wallet } from 'lucide-react';
import ShopLayout from '../../layouts/ShopLayout';
import { Button, EmptyState, Field, Input, PageHeader, Pagination, cx } from '../../components/ui';
import { ConfirmDialog, Modal } from '../../components/overlays';
import { uuid } from '../../lib';
import { submitOrQueue } from '../../offline';
import { useT } from '../../i18n';
import type { Paginated, SharedProps } from '../../types';

type Row = { id: number; amount: string; category: string; method: string; date: string; note: string | null; by: string | null };
type Props = {
    month: string; monthLabel: string; expenses: Paginated<Row>; total: string; byCategory: { label: string; total: string; amount: number }[];
    categories: Record<string, string>; methods: Record<string, string>; today: string;
};

function AddForm({ categories, methods, today, onDone }: { categories: Props['categories']; methods: Props['methods']; today: string; onDone: () => void }) {
    const t = useT();
    const [data, setData] = useState({ amount: '', category: '', payment_method: 'cash', spent_on: today, note: '' });
    const [errors, setErrors] = useState<Record<string, string>>({});
    const [busy, setBusy] = useState(false);
    const submit = (e: FormEvent) => {
        e.preventDefault();
        setBusy(true);
        submitOrQueue({
            url: route('expenses.store'), type: 'expense', label: `${categories[data.category] ?? 'Expense'} ${data.amount}`,
            data: { ...data, client_uuid: uuid() }, onSuccess: onDone, onQueued: onDone, onError: setErrors, onFinish: () => setBusy(false),
        });
    };
    return (
        <form onSubmit={submit} className="space-y-4" noValidate>
            <Field label={t('Amount')} error={errors.amount_minor}><Input inputMode="decimal" value={data.amount} onChange={(e) => setData({ ...data, amount: e.target.value })} autoFocus /></Field>
            <Field label={t('What was it for?')} error={errors.category}>
                <div className="grid grid-cols-2 gap-2">
                    {Object.entries(categories).map(([k, v]) => (
                        <button key={k} type="button" onClick={() => setData({ ...data, category: k })} className={cx('rounded-xl border-2 px-3 py-2.5 text-left text-sm font-bold', data.category === k ? 'border-brand bg-brand/[0.06] text-brand' : 'border-line text-ink-2')}>{t(v)}</button>
                    ))}
                </div>
            </Field>
            <Field label={t('Paid with')}>
                <div className="grid grid-cols-2 gap-2">
                    {Object.entries(methods).map(([k, v]) => (
                        <button key={k} type="button" onClick={() => setData({ ...data, payment_method: k })} className={cx('rounded-xl border-2 px-3 py-2 text-sm font-bold', data.payment_method === k ? 'border-brand bg-brand/[0.06] text-brand' : 'border-line text-ink-2')}>{t(v)}</button>
                    ))}
                </div>
            </Field>
            <Field label={t('Date')} error={errors.spent_on}><Input type="date" max={today} value={data.spent_on} onChange={(e) => setData({ ...data, spent_on: e.target.value })} /></Field>
            <Input placeholder={t('Note (optional)')} value={data.note} onChange={(e) => setData({ ...data, note: e.target.value })} />
            <Button type="submit" size="lg" className="w-full" disabled={busy}>{busy ? t('Saving…') : t('Add expense')}</Button>
        </form>
    );
}

const shiftMonth = (m: string, by: number) => { const [y, mo] = m.split('-').map(Number); const d = new Date(y, mo - 1 + by, 1); return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`; };

export default function Expenses({ month, monthLabel, expenses, total, byCategory, categories, methods, today }: Props) {
    const t = useT();
    const { auth } = usePage<SharedProps>().props;
    const owner = auth?.role === 'owner';
    const [adding, setAdding] = useState(false);
    const [removing, setRemoving] = useState<Row | null>(null);
    const go = (m: string) => router.get(route('expenses.index'), { month: m }, { preserveScroll: true });
    const max = Math.max(1, ...byCategory.map((c) => c.amount));

    return (
        <ShopLayout title="Expenses">
            <PageHeader title={t('Expenses')} actions={<Button icon={Plus} onClick={() => setAdding(true)}>{t('Add expense')}</Button>} />
            <div className="mb-4 flex items-center gap-2">
                <button onClick={() => go(shiftMonth(month, -1))} className="grid size-11 place-items-center rounded-xl bg-white ring-1 ring-line" aria-label="Month before"><ChevronLeft className="size-5" /></button>
                <p className="flex-1 text-center text-lg font-extrabold text-ink">{monthLabel}</p>
                <button onClick={() => go(shiftMonth(month, 1))} disabled={month >= today.slice(0, 7)} className="grid size-11 place-items-center rounded-xl bg-white ring-1 ring-line disabled:opacity-30" aria-label="Next month"><ChevronRight className="size-5" /></button>
            </div>
            <div className="mb-4 rounded-card bg-white p-4 shadow-card ring-1 ring-line">
                <p className="text-sm text-muted">{owner ? t('Total') : 'You recorded'}</p>
                <p className="text-3xl font-extrabold tracking-tight text-ink">{total}</p>
                {byCategory.length > 0 && (
                    <ul className="mt-3 space-y-2">
                        {byCategory.map((c) => (
                            <li key={c.label}>
                                <div className="flex justify-between text-sm"><span className="font-semibold text-ink-2">{t(c.label)}</span><span className="font-bold text-ink">{c.total}</span></div>
                                <div className="mt-1 h-2 overflow-hidden rounded-full bg-line-2"><div className="h-full rounded-full bg-brand" style={{ width: `${(c.amount / max) * 100}%` }} /></div>
                            </li>
                        ))}
                    </ul>
                )}
            </div>
            {expenses.data.length === 0 ? <EmptyState icon={Wallet}>No expenses this month.</EmptyState> : (
                <ul className="divide-y divide-line overflow-hidden rounded-card border border-line bg-white shadow-card">
                    {expenses.data.map((e) => (
                        <li key={e.id} className="flex items-center gap-3 px-4 py-3">
                            <div className="min-w-0 flex-1">
                                <p className="truncate text-[15px] font-bold text-ink">{t(e.category)}{e.note ? ` · ${e.note}` : ''}</p>
                                <p className="truncate text-xs text-muted">{e.date} · {t(e.method)}{e.by ? ` · ${e.by}` : ''}</p>
                            </div>
                            <p className="text-[15px] font-extrabold text-ink">{e.amount}</p>
                            {owner && <button onClick={() => setRemoving(e)} className="grid size-9 place-items-center rounded-lg text-muted hover:bg-rose-50 hover:text-rose-600" aria-label="Remove"><Trash2 className="size-4" /></button>}
                        </li>
                    ))}
                </ul>
            )}
            <Pagination page={expenses} />
            <Modal open={adding} onClose={() => setAdding(false)} title={t('Add expense')}>{adding && <AddForm categories={categories} methods={methods} today={today} onDone={() => setAdding(false)} />}</Modal>
            <ConfirmDialog open={!!removing} title="Remove this expense?" tone="danger" confirmLabel="Remove"
                onConfirm={() => removing && router.delete(route('expenses.destroy', { expense: removing.id }), { preserveScroll: true, onFinish: () => setRemoving(null) })} onCancel={() => setRemoving(null)}>
                {removing?.amount} · {removing?.category}. The activity log keeps a record.
            </ConfirmDialog>
        </ShopLayout>
    );
}
