import React, {useEffect, useMemo, useState} from 'react';
import {Link, usePage} from '@inertiajs/react';
import MainLayout from '@/layouts/MainLayout';
import AppPageHeader from '@/components/AppPageHeader';
import {makeGetRequest, makePostRequest} from '@/lib/request';
import {notify} from '@/lib/notify';
import {useCurrencyFormatter} from '@/lib/currency';

const STATUS_OPTIONS = [
    {value: '', label: 'All statuses'},
    {value: 'draft', label: 'Draft'},
    {value: 'sent', label: 'Sent'},
    {value: 'viewed', label: 'Viewed'},
    {value: 'partial_payment', label: 'Partial payment'},
    {value: 'paid', label: 'Paid'},
    {value: 'overdue', label: 'Overdue'},
    {value: 'cancelled', label: 'Cancelled'},
    {value: 'written_off', label: 'Written off'},
];

function dateLabel(value: any): string {
    return value ? new Date(value).toLocaleDateString() : '-';
}

function titleCase(value: string): string {
    return (value || '-').replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
}

function statusClass(status: string): string {
    switch (status) {
        case 'draft': return 'text-warning';
        case 'sent':
        case 'viewed': return 'text-info';
        case 'partial_payment': return 'text-primary';
        case 'paid': return 'text-success';
        case 'overdue': return 'text-danger';
        case 'cancelled':
        case 'written_off': return 'text-gray-500';
        default: return '';
    }
}

export default function Index(): JSX.Element {
    const {auth} = usePage<{ auth: { user: any } }>().props;
    const token = auth?.user?.token ?? auth?.user?.api_token ?? undefined;
    const money = useCurrencyFormatter(token);

    const [invoices, setInvoices] = useState<any[]>([]);
    const [loading, setLoading] = useState(false);
    const [page, setPage] = useState(1);
    const [meta, setMeta] = useState<any>(null);
    const [query, setQuery] = useState('');
    const [status, setStatus] = useState('');
    const [viewInvoice, setViewInvoice] = useState<any | null>(null);
    const [writeOffInvoice, setWriteOffInvoice] = useState<any | null>(null);
    const [writeOffReason, setWriteOffReason] = useState('');
    const [submitting, setSubmitting] = useState(false);

    useEffect(() => {
        fetchInvoices();
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [page, status, token]);

    useEffect(() => {
        const t = setTimeout(() => {
            setPage(1);
            fetchInvoices(1, query, status);
        }, 350);
        return () => clearTimeout(t);
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [query]);

    async function fetchInvoices(p = page, q = query, s = status) {
        setLoading(true);
        try {
            const params = new URLSearchParams({page: String(p)});
            if (q.trim()) params.append('search', q.trim());
            if (s) params.append('status', s);
            const res = await makeGetRequest(`/api/invoices?${params}`, {token});
            const payload = res.data?.result ?? res.data ?? {};
            const list = payload?.data ?? payload ?? [];
            setInvoices(Array.isArray(list) ? list : []);
            setMeta(payload?.meta ?? (payload?.data ? {
                current_page: payload.current_page ?? p,
                last_page: payload.last_page ?? 1,
                total: payload.total ?? 0,
            } : null));
        } catch (e: any) {
            notify.toastErrorMessage(e?.response?.data?.message || 'Failed to load invoices');
        } finally {
            setLoading(false);
        }
    }

    const summary = useMemo(() => ({
        total: invoices.reduce((sum, invoice) => sum + Number(invoice.total ?? 0), 0),
        paid: invoices.reduce((sum, invoice) => sum + Number(invoice.amount_paid ?? 0), 0),
        outstanding: invoices.reduce((sum, invoice) => sum + Number(invoice.balance_due ?? 0), 0),
    }), [invoices]);

    const gotoPage = (p: number) => {
        if (p < 1 || p > (meta?.last_page ?? p)) return;
        setPage(p);
    };

    const runInvoiceAction = async (invoice: any, action: 'send' | 'cancel' | 'reminder') => {
        const prompts: Record<string, string> = {
            send: 'Send this invoice to the client?',
            cancel: 'Cancel this invoice and release its line items?',
            reminder: 'Send a payment reminder for this invoice?',
        };
        if (!confirm(prompts[action])) return;
        try {
            await makePostRequest(`/api/invoices/${invoice.id}/${action}`, {}, {token});
            notify.toastSuccessMessage(action === 'reminder' ? 'Reminder sent' : `Invoice ${action === 'send' ? 'sent' : 'cancelled'}`);
            fetchInvoices();
        } catch (e: any) {
            notify.toastErrorMessage(e?.response?.data?.message || 'Action failed');
        }
    };

    const submitWriteOff = async (e: React.FormEvent) => {
        e.preventDefault();
        if (!writeOffInvoice || writeOffReason.trim().length < 5) return;
        setSubmitting(true);
        try {
            await makePostRequest(`/api/invoices/${writeOffInvoice.id}/write-off`, {reason: writeOffReason.trim()}, {token});
            notify.toastSuccessMessage('Invoice written off');
            setWriteOffInvoice(null);
            setWriteOffReason('');
            fetchInvoices();
        } catch (err: any) {
            notify.toastErrorMessage(err?.response?.data?.message || 'Failed to write off invoice');
        } finally {
            setSubmitting(false);
        }
    };

    return (
        <MainLayout>
            <AppPageHeader title="Invoices" subtitle="Billing" />

            <div className="grid grid-cols-12 gap-6 mb-6">
                <div className="col-span-12 sm:col-span-4"><div className="box"><div className="box-body"><p className="text-sm text-gray-500 mb-1">Page total</p><p className="text-2xl font-semibold">{money(summary.total)}</p></div></div></div>
                <div className="col-span-12 sm:col-span-4"><div className="box"><div className="box-body"><p className="text-sm text-gray-500 mb-1">Paid</p><p className="text-2xl font-semibold text-success">{money(summary.paid)}</p></div></div></div>
                <div className="col-span-12 sm:col-span-4"><div className="box"><div className="box-body"><p className="text-sm text-gray-500 mb-1">Outstanding</p><p className="text-2xl font-semibold text-danger">{money(summary.outstanding)}</p></div></div></div>
            </div>

            <div className="grid grid-cols-12 gap-6">
                <div className="col-span-12">
                    <div className="box"><div className="box-body">
                        <div className="flex flex-wrap justify-between gap-4 mb-5">
                            <div className="flex flex-wrap items-center gap-3">
                                <div className="relative sm:max-w-xs max-w-[220px]">
                                    <div className="absolute inset-y-0 end-0 flex items-center pointer-events-none pe-4"><i className="ti ti-search"></i></div>
                                    <input type="text" className="p-2 pe-10 ti-form-input" placeholder="Search invoices" value={query} onChange={e => setQuery(e.target.value)} />
                                </div>
                                <select className="ti-form-input w-auto" value={status} onChange={e => { setStatus(e.target.value); setPage(1); }}>
                                    {STATUS_OPTIONS.map(option => <option key={option.value} value={option.value}>{option.label}</option>)}
                                </select>
                            </div>
                            <div className="flex gap-2">
                                <Link href="/invoices/overdue" className="ti-btn ti-btn-soft-danger py-2 px-3 whitespace-nowrap">Overdue</Link>
                                <Link href="/invoices/create" className="ti-btn ti-btn-primary py-2 px-3 whitespace-nowrap"><i className="ri ri-add-line mr-2"></i>Create Invoice</Link>
                            </div>
                        </div>

                        <div className="rounded-sm overflow-auto todo-table w-full">
                            <table className="ti-custom-table ti-custom-table-head whitespace-nowrap w-full">
                                <thead className="bg-gray-100 dark:bg-bodybg"><tr>
                                    <th>Invoice</th><th>Client</th><th>Matter</th><th>Issued</th><th>Due</th><th>Total</th><th>Paid</th><th>Balance</th><th>Status</th><th className="!text-end">Action</th>
                                </tr></thead>
                                <tbody>
                                {loading ? <tr><td colSpan={10} className="text-center py-8">Loading...</td></tr> : invoices.length === 0 ? <tr><td colSpan={10} className="text-center py-8">No invoices found.</td></tr> : invoices.map(invoice => (
                                    <tr key={invoice.id}>
                                        <td className="font-semibold text-indigo-600">{invoice.invoice_number}</td>
                                        <td>{invoice.client?.name ?? '-'}</td>
                                        <td>{invoice.matter?.reference_number ?? '-'}</td>
                                        <td>{dateLabel(invoice.issued_date)}</td>
                                        <td>{dateLabel(invoice.due_date)}</td>
                                        <td>{money(invoice.total)}</td>
                                        <td>{money(invoice.amount_paid)}</td>
                                        <td>{money(invoice.balance_due)}</td>
                                        <td><span className={statusClass(invoice.status)}>{titleCase(invoice.status)}</span></td>
                                        <td className="text-end font-medium">
                                            <div className="inline-flex gap-2">
                                                <button type="button" className="w-8 h-8 ti-btn rounded-full p-0 ti-btn-soft-secondary" title="View" onClick={() => setViewInvoice(invoice)}><i className="ti ti-eye"></i></button>
                                                {invoice.status === 'draft' && <button type="button" className="w-8 h-8 ti-btn rounded-full p-0 ti-btn-soft-info" title="Send" onClick={() => runInvoiceAction(invoice, 'send')}><i className="ti ti-send"></i></button>}
                                                {['draft', 'sent', 'viewed'].includes(invoice.status) && <button type="button" className="w-8 h-8 ti-btn rounded-full p-0 ti-btn-soft-danger" title="Cancel" onClick={() => runInvoiceAction(invoice, 'cancel')}><i className="ti ti-ban"></i></button>}
                                                {['sent', 'viewed', 'partial_payment', 'overdue'].includes(invoice.status) && <button type="button" className="w-8 h-8 ti-btn rounded-full p-0 ti-btn-soft-warning" title="Reminder" onClick={() => runInvoiceAction(invoice, 'reminder')}><i className="ti ti-bell"></i></button>}
                                                {!['paid', 'cancelled', 'written_off'].includes(invoice.status) && <button type="button" className="w-8 h-8 ti-btn rounded-full p-0 ti-btn-soft-danger" title="Write off" onClick={() => setWriteOffInvoice(invoice)}><i className="ti ti-file-x"></i></button>}
                                            </div>
                                        </td>
                                    </tr>
                                ))}
                                </tbody>
                            </table>
                        </div>

                        <div className="flex items-center justify-between mt-4">
                            <div className="text-sm text-gray-600">showing {invoices.length} of {meta?.total ?? 0} items</div>
                            <div className="flex items-center gap-2">
                                <button type="button" disabled={(meta?.current_page ?? 1) <= 1} onClick={() => gotoPage((meta?.current_page ?? 1) - 1)} className="px-2 py-1 border rounded disabled:opacity-40">Prev</button>
                                {Array.from({length: meta?.last_page ?? 1}).map((_, i) => <button key={i + 1} type="button" onClick={() => gotoPage(i + 1)} className={`px-2 py-1 border rounded ${i + 1 === (meta?.current_page ?? page) ? 'bg-indigo-600 text-white' : ''}`}>{i + 1}</button>)}
                                <button type="button" disabled={(meta?.current_page ?? 1) >= (meta?.last_page ?? 1)} onClick={() => gotoPage((meta?.current_page ?? 1) + 1)} className="px-2 py-1 border rounded disabled:opacity-40">Next</button>
                            </div>
                        </div>
                    </div></div>
                </div>
            </div>

            {viewInvoice && <InvoiceViewModal invoice={viewInvoice} money={money} onClose={() => setViewInvoice(null)} />}
            {writeOffInvoice && (
                <div role="dialog" aria-modal="true" className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-sm p-4">
                    <div className="bg-white rounded-xl shadow-xl w-full max-w-md">
                        <form onSubmit={submitWriteOff} noValidate>
                            <div className="flex items-center justify-between px-5 py-4 border-b border-gray-200"><h3 className="text-base font-semibold text-gray-800">Write Off Invoice</h3><button type="button" className="p-1.5 text-gray-400 hover:text-gray-600 rounded" onClick={() => setWriteOffInvoice(null)}><i className="ri ri-close-line text-lg"></i></button></div>
                            <div className="px-5 py-5 space-y-4">
                                <p className="text-sm text-gray-600">Provide a reason for writing off {writeOffInvoice.invoice_number}.</p>
                                <textarea className="ti-form-input" rows={4} value={writeOffReason} onChange={e => setWriteOffReason(e.target.value)} placeholder="Reason" />
                            </div>
                            <div className="flex items-center justify-end gap-2 px-5 py-4 border-t border-gray-200"><button type="button" onClick={() => setWriteOffInvoice(null)} className="px-4 py-2 text-sm border rounded-lg hover:bg-gray-50">Cancel</button><button type="submit" disabled={submitting || writeOffReason.trim().length < 5} className="ti-btn ti-btn-danger px-4 py-2">{submitting ? 'Saving...' : 'Write off'}</button></div>
                        </form>
                    </div>
                </div>
            )}
        </MainLayout>
    );
}

function InvoiceViewModal({invoice, money, onClose}: { invoice: any; money: (value: any) => string; onClose: () => void }): JSX.Element {
    return (
        <div role="dialog" aria-modal="true" className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-sm p-4">
            <div className="bg-white rounded-xl shadow-xl w-full max-w-3xl max-h-[90vh] overflow-auto">
                <div className="flex items-center justify-between px-5 py-4 border-b border-gray-200 sticky top-0 bg-white z-10"><h3 className="text-base font-semibold text-gray-800">Invoice {invoice.invoice_number}</h3><button type="button" className="p-1.5 text-gray-400 hover:text-gray-600 rounded" onClick={onClose}><i className="ri ri-close-line text-lg"></i></button></div>
                <div className="px-5 py-5 space-y-5">
                    <div className="grid grid-cols-1 sm:grid-cols-3 gap-4 text-sm">
                        <div><p className="text-gray-500">Client</p><p className="font-medium">{invoice.client?.name ?? '-'}</p></div>
                        <div><p className="text-gray-500">Matter</p><p className="font-medium">{invoice.matter?.reference_number ?? '-'}</p></div>
                        <div><p className="text-gray-500">Status</p><p className={statusClass(invoice.status)}>{titleCase(invoice.status)}</p></div>
                    </div>
                    <table className="ti-custom-table ti-custom-table-head whitespace-nowrap w-full">
                        <thead className="bg-gray-100"><tr><th>Date</th><th>Type</th><th>Description</th><th>Qty</th><th>Rate</th><th>Amount</th></tr></thead>
                        <tbody>{(invoice.line_items ?? invoice.lineItems ?? []).map((item: any) => <tr key={item.id}><td>{dateLabel(item.item_date)}</td><td>{titleCase(item.type)}</td><td className="max-w-xs truncate">{item.description}</td><td>{item.quantity}</td><td>{money(item.rate)}</td><td>{money(item.amount)}</td></tr>)}</tbody>
                    </table>
                    <div className="flex justify-end"><div className="w-full max-w-xs space-y-2 text-sm"><div className="flex justify-between"><span>Subtotal</span><span>{money(invoice.subtotal)}</span></div><div className="flex justify-between"><span>Tax</span><span>{money(invoice.tax_amount)}</span></div><div className="flex justify-between font-semibold"><span>Total</span><span>{money(invoice.total)}</span></div><div className="flex justify-between"><span>Paid</span><span>{money(invoice.amount_paid)}</span></div><div className="flex justify-between text-danger font-semibold"><span>Balance</span><span>{money(invoice.balance_due)}</span></div></div></div>
                    {invoice.notes && <div><p className="text-sm font-medium mb-1">Notes</p><p className="text-sm text-gray-600 whitespace-pre-wrap">{invoice.notes}</p></div>}
                </div>
            </div>
        </div>
    );
}
