import { useEffect, useMemo, useState } from 'react';
import { faMagnifyingGlass } from '@fortawesome/pro-duotone-svg-icons';
import { faIcon } from '@/lib/icon-wrapper';

const SearchLg = faIcon(faMagnifyingGlass);
import { Badge } from '@/components/base/badges/badges';
import { Input } from '@/components/base/input/input';
import { Table } from '@/components/application/table/table';
import { PaginationCardDefault } from '@/components/application/pagination/pagination';
import { Tabs, TabList, Tab } from '@/components/application/tabs/tabs';
import { TopBar } from '@/components/layout/top-bar';
import { PhoneActionCell } from '@/components/call-desk/phone-action-cell';
import { formatPhone, formatDateOnly, formatTimeOnly } from '@/lib/format';
import { apiClient } from '@/lib/api-client';

type AppointmentRecord = {
    id: string;
    scheduledAt: string | null;
    durationMin: number | null;
    appointmentType: string | null;
    status: string | null;
    doctorName: string | null;
    department: string | null;
    reasonForVisit: string | null;
    patient: {
        id: string;
        fullName: { firstName: string; lastName: string } | null;
        phones: { primaryPhoneNumber: string } | null;
    } | null;
    doctor: {
        clinic: { clinicName: string } | null;
    } | null;
};

type StatusTab = 'all' | 'SCHEDULED' | 'COMPLETED' | 'CANCELLED' | 'RESCHEDULED';

const STATUS_COLORS: Record<string, 'brand' | 'success' | 'error' | 'warning' | 'gray'> = {
    SCHEDULED: 'brand',
    CONFIRMED: 'brand',
    COMPLETED: 'success',
    CANCELLED: 'error',
    NO_SHOW: 'warning',
    RESCHEDULED: 'warning',
};

const STATUS_LABELS: Record<string, string> = {
    SCHEDULED: 'Booked',
    CONFIRMED: 'Confirmed',
    COMPLETED: 'Completed',
    CANCELLED: 'Cancelled',
    NO_SHOW: 'No Show',
    RESCHEDULED: 'Rescheduled',
    FOLLOW_UP: 'Follow-up',
    CONSULTATION: 'Consultation',
};

const QUERY = `{ appointments(first: 100, orderBy: [{ scheduledAt: DescNullsLast }]) { edges { node {
    id scheduledAt durationMin appointmentType status
    doctorName department reasonForVisit
    patient { id fullName { firstName lastName } phones { primaryPhoneNumber } }
    doctor { id clinic { clinicName } }
} } } }`;

const formatDate = (iso: string): string => formatDateOnly(iso);

const formatTime = (iso: string): string => formatTimeOnly(iso);

export const AppointmentsPage = () => {
    const [appointments, setAppointments] = useState<AppointmentRecord[]>([]);
    const [loading, setLoading] = useState(true);
    const [tab, setTab] = useState<StatusTab>('all');
    const [search, setSearch] = useState('');
    const [page, setPage] = useState(1);
    const PAGE_SIZE = 20;

    useEffect(() => {
        apiClient.graphql<{ appointments: { edges: Array<{ node: AppointmentRecord }> } }>(QUERY, undefined, { silent: true })
            .then(data => setAppointments(data.appointments.edges.map(e => e.node)))
            .catch(() => {})
            .finally(() => setLoading(false));
    }, []);

    const statusCounts = useMemo(() => {
        const counts: Record<string, number> = {};
        for (const a of appointments) {
            const s = a.status ?? 'UNKNOWN';
            counts[s] = (counts[s] ?? 0) + 1;
        }
        return counts;
    }, [appointments]);

    const filtered = useMemo(() => {
        let rows = appointments;

        if (tab !== 'all') {
            rows = rows.filter(a => a.status === tab);
        }

        if (search.trim()) {
            const q = search.toLowerCase();
            rows = rows.filter(a => {
                const patientName = `${a.patient?.fullName?.firstName ?? ''} ${a.patient?.fullName?.lastName ?? ''}`.toLowerCase();
                const phone = a.patient?.phones?.primaryPhoneNumber ?? '';
                const doctor = (a.doctorName ?? '').toLowerCase();
                const dept = (a.department ?? '').toLowerCase();
                const branch = (a.doctor?.clinic?.clinicName ?? '').toLowerCase();
                return patientName.includes(q) || phone.includes(q) || doctor.includes(q) || dept.includes(q) || branch.includes(q);
            });
        }

        return rows;
    }, [appointments, tab, search]);

    const totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
    const pagedRows = filtered.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);

    // Reset page on filter/search change
    useEffect(() => { setPage(1); }, [tab, search]);

    const tabItems = [
        { id: 'all' as const, label: 'All', badge: appointments.length > 0 ? String(appointments.length) : undefined },
        { id: 'SCHEDULED' as const, label: 'Booked', badge: statusCounts.SCHEDULED ? String(statusCounts.SCHEDULED) : undefined },
        { id: 'COMPLETED' as const, label: 'Completed', badge: statusCounts.COMPLETED ? String(statusCounts.COMPLETED) : undefined },
        { id: 'CANCELLED' as const, label: 'Cancelled', badge: statusCounts.CANCELLED ? String(statusCounts.CANCELLED) : undefined },
        { id: 'RESCHEDULED' as const, label: 'Rescheduled', badge: statusCounts.RESCHEDULED ? String(statusCounts.RESCHEDULED) : undefined },
    ];

    return (
        <>
            <TopBar title="Appointment Master" />

            <div className="flex flex-1 flex-col overflow-hidden">
                {/* Tabs + search */}
                <div className="flex shrink-0 items-end justify-between border-b border-secondary px-6 pt-3 pb-0.5">
                    <Tabs selectedKey={tab} onSelectionChange={(key) => setTab(key as StatusTab)}>
                        <TabList items={tabItems} type="underline" size="sm">
                            {(item) => <Tab key={item.id} id={item.id} label={item.label} badge={item.badge} />}
                        </TabList>
                    </Tabs>
                    <div className="w-56 shrink-0 pb-1">
                        <Input
                            placeholder="Search patient, doctor, branch..."
                            icon={SearchLg}
                            size="sm"
                            value={search}
                            onChange={setSearch}
                            aria-label="Search appointments"
                        />
                    </div>
                </div>

                {/* Table */}
                <div className="flex flex-1 flex-col overflow-hidden px-4 pt-3">
                    {loading ? (
                        <div className="flex items-center justify-center py-12">
                            <p className="text-sm text-tertiary">Loading appointments...</p>
                        </div>
                    ) : filtered.length === 0 ? (
                        <div className="flex items-center justify-center py-12">
                            <p className="text-sm text-quaternary">{search ? 'No matching appointments' : 'No appointments found'}</p>
                        </div>
                    ) : (
                        <Table size="sm">
                            <Table.Header>
                                <Table.Head label="Patient" isRowHeader />
                                <Table.Head label="Date" className="w-28" />
                                <Table.Head label="Time" className="w-24" />
                                <Table.Head label="Doctor" />
                                <Table.Head label="Department" className="w-28" />
                                <Table.Head label="Branch" className="w-36" />
                                <Table.Head label="Status" className="w-28" />
                                <Table.Head label="Chief Complaint" />
                            </Table.Header>
                            <Table.Body items={pagedRows}>
                                {(appt) => {
                                    const patientName = appt.patient
                                        ? `${appt.patient.fullName?.firstName ?? ''} ${appt.patient.fullName?.lastName ?? ''}`.trim() || 'Unknown'
                                        : 'Unknown';
                                    const phone = appt.patient?.phones?.primaryPhoneNumber ?? '';
                                    const branch = appt.doctor?.clinic?.clinicName ?? '—';
                                    const statusLabel = STATUS_LABELS[appt.status ?? ''] ?? appt.status ?? '—';
                                    const statusColor = STATUS_COLORS[appt.status ?? ''] ?? 'gray';

                                    return (
                                        <Table.Row id={appt.id}>
                                            <Table.Cell>
                                                <div className="min-w-0">
                                                    <span className="text-sm font-medium text-primary block truncate max-w-[180px]">
                                                        {patientName}
                                                    </span>
                                                    {phone && (
                                                        <PhoneActionCell
                                                            phoneNumber={phone}
                                                            displayNumber={formatPhone({ number: phone, callingCode: '+91' })}
                                                        />
                                                    )}
                                                </div>
                                            </Table.Cell>
                                            <Table.Cell>
                                                <span className="text-sm text-primary">
                                                    {appt.scheduledAt ? formatDate(appt.scheduledAt) : '—'}
                                                </span>
                                            </Table.Cell>
                                            <Table.Cell>
                                                <span className="text-sm text-primary">
                                                    {appt.scheduledAt ? formatTime(appt.scheduledAt) : '—'}
                                                </span>
                                            </Table.Cell>
                                            <Table.Cell>
                                                <span className="text-sm text-primary">{appt.doctorName ?? '—'}</span>
                                            </Table.Cell>
                                            <Table.Cell>
                                                <span className="text-xs text-tertiary">{appt.department ?? '—'}</span>
                                            </Table.Cell>
                                            <Table.Cell>
                                                <span className="text-xs text-tertiary truncate block max-w-[130px]">{branch}</span>
                                            </Table.Cell>
                                            <Table.Cell>
                                                <Badge size="sm" color={statusColor} type="pill-color">
                                                    {statusLabel}
                                                </Badge>
                                            </Table.Cell>
                                            <Table.Cell>
                                                <span className="text-xs text-tertiary truncate block max-w-[200px]">
                                                    {appt.reasonForVisit ?? '—'}
                                                </span>
                                            </Table.Cell>
                                        </Table.Row>
                                    );
                                }}
                            </Table.Body>
                        </Table>
                    )}
                    <div className="shrink-0">
                        <PaginationCardDefault
                            page={page}
                            total={totalPages}
                            onPageChange={setPage}
                        />
                    </div>
                </div>
            </div>
        </>
    );
};
