import React, {useEffect, useState} from 'react';
import {Link} from '@inertiajs/react';
import ListingPagination from '@/components/ListingPagination';
import Modal from '@/components/ui/modal/Modal';
import {makeGetRequest} from '@/lib/request';
import {notify} from '@/lib/notify';

type Props = {record: any; team: any[]; token?: string};

const categoryOptions = ['matter_lifecycle', 'litigation', 'evidence', 'witness', 'court_docket', 'legal_team'];
const categoryIcons: Record<string, string> = {
    matter_lifecycle: 'fa-briefcase', litigation: 'fa-gavel', evidence: 'fa-archive',
    witness: 'fa-users', court_docket: 'fa-calendar-check-o', legal_team: 'fa-user-circle-o',
};

export default function TimelineWorkspace({record, team, token}: Props): JSX.Element {
    const [events, setEvents] = useState<any[]>([]);
    const [upcoming, setUpcoming] = useState<any[]>([]);
    const [eventTypes, setEventTypes] = useState<string[]>([]);
    const [loading, setLoading] = useState(true);
    const [selected, setSelected] = useState<any | null>(null);
    const [page, setPage] = useState(1);
    const [meta, setMeta] = useState({current_page: 1, last_page: 1, total: 0});
    const [filters, setFilters] = useState({
        search: '', category: '', event_type: '', responsible_user_id: '', hearing_id: '',
        document_type: '', date_from: '', date_to: '', order: 'desc',
    });

    async function load() {
        setLoading(true);
        try {
            const params = new URLSearchParams({page: String(page), order: filters.order});
            Object.entries(filters).forEach(([key, value]) => { if (value && key !== 'order') params.set(key, value); });
            const response = await makeGetRequest(`/api/litigation/${record.id}/timeline?${params}`, {token});
            const payload = response.data?.result ?? response.data ?? {};
            const pagination = payload.events ?? {};
            setEvents(pagination.data ?? []);
            setMeta({current_page: pagination.current_page ?? page, last_page: pagination.last_page ?? 1, total: pagination.total ?? 0});
            setUpcoming(payload.upcoming_events ?? []);
            setEventTypes(payload.filters?.event_types ?? []);
        } catch (error: any) {
            notify.toastErrorMessage(firstError(error) || 'Unable to load litigation timeline');
        } finally {
            setLoading(false);
        }
    }

    useEffect(() => {
        const timer = window.setTimeout(load, 250);
        return () => window.clearTimeout(timer);
    }, [record.id, token, page, JSON.stringify(filters)]);

    function updateFilter(key: string, value: string) {
        setPage(1);
        setFilters(current => ({...current, [key]: value}));
    }

    return <>
        <div className="mb-5 flex flex-wrap items-start justify-between gap-3">
            <div>
                <h5 className="font-semibold">Consolidated litigation timeline</h5>
                <p className="text-sm text-gray-500">A read-only chronology assembled from the case's authoritative matter, court, evidence, witness, docket, and team records.</p>
            </div>
            <button type="button" className="ti-btn ti-btn-light" onClick={() => updateFilter('order', filters.order === 'desc' ? 'asc' : 'desc')}>
                <i className={`fa ${filters.order === 'desc' ? 'fa-sort-amount-desc' : 'fa-sort-amount-asc'} me-2`} />
                {filters.order === 'desc' ? 'Newest first' : 'Oldest first'}
            </button>
        </div>

        {upcoming.length ? <section className="mb-6 rounded-xl border bg-gray-50 p-4 dark:bg-bodybg" aria-labelledby="upcoming-events-title">
            <div className="mb-3 flex items-center gap-2"><i className="fa fa-clock-o text-primary" /><h6 id="upcoming-events-title" className="font-semibold">Upcoming events</h6></div>
            <div className="grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3">
                {upcoming.map(event => <Link key={event.id} href={event.source_url} className="rounded-lg border bg-white p-3 transition hover:border-primary dark:bg-bodybg">
                    <div className="text-xs font-medium uppercase tracking-wide text-primary">{dateTime(event.occurred_at)}</div>
                    <div className="mt-1 font-semibold">{event.title}</div>
                    <div className="mt-2 flex items-center justify-between gap-2 text-xs text-gray-500"><span>{label(event.category)}</span><Badge value={event.status} /></div>
                </Link>)}
            </div>
        </section> : null}

        <div className="mb-6 grid grid-cols-1 gap-3 md:grid-cols-3 xl:grid-cols-4">
            <input className="ti-form-input md:col-span-2" placeholder="Search titles and descriptions…" value={filters.search} onChange={event => updateFilter('search', event.target.value)} />
            <Select value={filters.category} first="All event categories" values={categoryOptions} onChange={value => updateFilter('category', value)} />
            <Select value={filters.event_type} first="All event types" values={eventTypes} onChange={value => updateFilter('event_type', value)} />
            <select className="ti-form-input" value={filters.responsible_user_id} onChange={event => updateFilter('responsible_user_id', event.target.value)}>
                <option value="">All responsible lawyers</option>
                {team.map(user => <option key={user.id} value={user.id}>{user.name}</option>)}
            </select>
            <select className="ti-form-input" value={filters.hearing_id} onChange={event => updateFilter('hearing_id', event.target.value)}>
                <option value="">All court hearings</option>
                {(record.proceedings ?? []).map((hearing: any) => <option key={hearing.id} value={hearing.id}>{hearing.calendar_event?.title ?? label(hearing.hearing_type)}</option>)}
            </select>
            <select className="ti-form-input" value={filters.document_type} onChange={event => updateFilter('document_type', event.target.value)}>
                <option value="">All filing types</option>
                {[...new Set((record.pleadings ?? []).map((pleading: any) => pleading.document_type))].map((type: any) => <option key={type} value={type}>{label(type)}</option>)}
            </select>
            <div className="grid grid-cols-2 gap-2">
                <input aria-label="Timeline start date" type="date" className="ti-form-input" value={filters.date_from} onChange={event => updateFilter('date_from', event.target.value)} />
                <input aria-label="Timeline end date" type="date" className="ti-form-input" value={filters.date_to} onChange={event => updateFilter('date_to', event.target.value)} />
            </div>
        </div>

        {loading ? <div className="py-14 text-center text-gray-500"><i className="fa fa-spinner fa-spin me-2" />Loading timeline…</div>
            : events.length === 0 ? <div className="rounded-lg border border-dashed py-14 text-center text-gray-500">No litigation events match the selected filters.</div>
                : <div className="relative ms-3 border-s-2 border-gray-200 ps-7 dark:border-white/10">
                    {events.map(event => <article key={event.id} className="relative mb-6 last:mb-0">
                        <span className="absolute -start-[2.65rem] top-0 flex h-8 w-8 items-center justify-center rounded-full bg-primary text-white ring-4 ring-white dark:ring-bodybg">
                            <i className={`fa ${categoryIcons[event.category] ?? 'fa-circle-o'} text-xs`} />
                        </span>
                        <div className="rounded-xl border p-4 transition hover:border-primary/50">
                            <div className="flex flex-wrap items-start justify-between gap-3">
                                <div>
                                    <div className="mb-1 flex flex-wrap items-center gap-2 text-xs text-gray-500">
                                        <span>{dateTime(event.occurred_at)}</span><span>•</span><span>{label(event.category)}</span>
                                        {event.status ? <Badge value={event.status} /> : null}
                                    </div>
                                    <button type="button" className="text-start font-semibold text-primary hover:underline" onClick={() => setSelected(event)}>{event.title}</button>
                                </div>
                                <Link href={event.source_url} className="ti-btn ti-btn-sm ti-btn-light" title="Open original record"><i className="fa fa-external-link me-2" />Open source</Link>
                            </div>
                            {event.description ? <p className="mt-2 text-sm text-gray-600 dark:text-gray-400">{event.description}</p> : null}
                            <div className="mt-3 flex flex-wrap gap-x-5 gap-y-1 text-xs text-gray-500">
                                {event.responsible_user ? <span><i className="fa fa-user me-1" />{event.responsible_user.name}</span> : null}
                                <span><i className="fa fa-database me-1" />{label(event.source_module)} #{event.source_record_id}</span>
                                {event.related_document ? <span><i className="fa fa-file-text-o me-1" />{event.related_document.title}</span> : null}
                                {event.recorded_at !== event.occurred_at ? <span title="Date entered into the system"><i className="fa fa-pencil-square-o me-1" />Recorded {dateTime(event.recorded_at)}</span> : null}
                            </div>
                        </div>
                    </article>)}
                </div>}

        <ListingPagination currentPage={meta.current_page} lastPage={meta.last_page} total={meta.total} itemCount={events.length} onPageChange={setPage} className="mt-5 px-1 pb-2" />

        {selected ? <Modal open={true} onClose={() => setSelected(null)} title={selected.title} footer={<><button type="button" className="ti-btn ti-btn-light" onClick={() => setSelected(null)}>Close</button><Link href={selected.source_url} className="ti-btn ti-btn-primary"><i className="fa fa-external-link me-2" />Open source record</Link></>}>
            <dl className="grid grid-cols-1 gap-4 text-sm sm:grid-cols-2">
                <Detail title="Occurred" value={dateTime(selected.occurred_at)} /><Detail title="Recorded" value={dateTime(selected.recorded_at)} />
                <Detail title="Category" value={label(selected.category)} /><Detail title="Event type" value={label(selected.event_type)} />
                <Detail title="Responsible user" value={selected.responsible_user?.name ?? 'Not recorded'} /><Detail title="Status" value={label(selected.status) || 'Not recorded'} />
                <Detail title="Source" value={`${label(selected.source_module)} #${selected.source_record_id}`} /><Detail title="Related document" value={selected.related_document?.title ?? 'None'} />
                <div className="sm:col-span-2"><Detail title="Description" value={selected.description ?? 'No additional details recorded.'} /></div>
            </dl>
        </Modal> : null}
    </>;
}

function Select({value, first, values, onChange}: any): JSX.Element {
    return <select className="ti-form-input" value={value} onChange={event => onChange(event.target.value)}><option value="">{first}</option>{values.map((item: string) => <option key={item} value={item}>{label(item)}</option>)}</select>;
}
function Detail({title, value}: {title: string; value: string}): JSX.Element { return <div><dt className="text-xs uppercase tracking-wide text-gray-500">{title}</dt><dd className="mt-1 break-words font-medium">{value}</dd></div>; }
function Badge({value}: {value?: string}): JSX.Element { const danger = ['overdue', 'cancelled', 'rejected', 'did_not_appear'].includes(value ?? ''); const success = ['completed', 'accepted', 'admitted', 'appeared', 'verified', 'served'].includes(value ?? ''); return <span className={`badge ${danger ? 'bg-danger/10 text-danger' : success ? 'bg-success/10 text-success' : 'bg-primary/10 text-primary'}`}>{label(value)}</span>; }
function label(value: string = ''): string { return String(value ?? '').replaceAll('_', ' ').replace(/\b\w/g, letter => letter.toUpperCase()); }
function dateTime(value?: string): string { return value ? new Date(value).toLocaleString() : '—'; }
function firstError(error: any): string | null { const errors = error?.response?.data?.errors; return errors ? String(Object.values(errors).flat()[0] ?? '') : error?.response?.data?.message ?? null; }
