import * as React from 'react';
import {
    analyticsReportApi,
    type AnalyticsEvent,
    type AnalyticsEventName,
} from '@/features/admin/dashboard/services/api';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Select } from '@/components/ui/select';
import {
    Table,
    TableBody,
    TableCell,
    TableEmpty,
    TableHead,
    TableHeaderCell,
    TableRow,
} from '@/components/ui/table';
import { Pagination } from '@/components/ui/pagination';
import { Spinner } from '@/components/ui/spinner';
import { toast } from '@/components/ui/sonner';
import { debounce, downloadBlob, formatDate } from '@/lib/utils';

interface AnalyticsReportProps {
    from: string;
    to: string;
}

const EVENT_OPTIONS: { value: AnalyticsEventName; label: string }[] = [
    { value: 'qr_scanned', label: 'QR scanned' },
    { value: 'otp_sent', label: 'OTP sent' },
    { value: 'otp_verified', label: 'OTP verified' },
    { value: 'quiz_started', label: 'Quiz started' },
    { value: 'question_answered', label: 'Question answered' },
    { value: 'question_timeout', label: 'Question timeout' },
    { value: 'quiz_completed', label: 'Quiz completed' },
    { value: 'offer_unlocked', label: 'Offer unlocked' },
    { value: 'offer_sms_sent', label: 'Offer SMS sent' },
    { value: 'app_link_clicked', label: 'App link clicked' },
];

function eventLabel(event: AnalyticsEventName): string {
    return (
        EVENT_OPTIONS.find((option) => option.value === event)?.label ?? event
    );
}

function payloadSummary(event: AnalyticsEvent): string {
    const payload = Object.fromEntries(
        Object.entries(event.payload).filter(
            ([key]) =>
                !['ip', 'user_agent'].includes(key) && !key.startsWith('utm_'),
        ),
    );

    return JSON.stringify(payload, null, 2);
}

export function AnalyticsReport({ from, to }: AnalyticsReportProps) {
    const [events, setEvents] = React.useState<AnalyticsEvent[]>([]);
    const [meta, setMeta] = React.useState({
        page: 1,
        lastPage: 1,
        total: 0,
        perPage: 25,
    });
    const [loading, setLoading] = React.useState(true);
    const [exporting, setExporting] = React.useState<'csv' | 'xlsx' | null>(
        null,
    );
    const [search, setSearch] = React.useState('');
    const [event, setEvent] = React.useState<AnalyticsEventName | ''>('');

    const filters = React.useMemo(
        () => ({
            date_from: from || undefined,
            date_to: to || undefined,
            event: event || undefined,
            search: search || undefined,
            per_page: 25,
        }),
        [event, from, search, to],
    );

    const load = React.useCallback(
        (page: number) => {
            setLoading(true);
            analyticsReportApi
                .index({ page, ...filters })
                .then((response) => {
                    setEvents(response.data || []);
                    setMeta({
                        page: response.meta?.current_page || 1,
                        lastPage: response.meta?.last_page || 1,
                        total: response.meta?.total || 0,
                        perPage: response.meta?.per_page || 25,
                    });
                })
                .catch(() => toast.error('Failed to load analytics events.'))
                .finally(() => setLoading(false));
        },
        [filters],
    );

    React.useEffect(() => load(1), [load]);

    const debouncedSearch = React.useMemo(
        () => debounce((value: string) => setSearch(value), 300),
        [],
    );

    async function handleExport(format: 'csv' | 'xlsx') {
        setExporting(format);
        try {
            const blob = await analyticsReportApi.export(filters, format);
            downloadBlob(
                blob,
                `analytics-events-${new Date().toISOString().slice(0, 10)}.${format}`,
            );
        } catch {
            toast.error(
                `Failed to export analytics events as ${format.toUpperCase()}.`,
            );
        } finally {
            setExporting(null);
        }
    }

    return (
        <Card>
            <CardHeader>
                <div className="flex flex-wrap items-center justify-between gap-4">
                    <div>
                        <CardTitle>Detailed analytics report</CardTitle>
                        <p className="mt-1 text-sm text-(--color-ink-muted)">
                            One row per tracked event in the selected date
                            range.
                        </p>
                    </div>
                    <div className="flex flex-wrap gap-2">
                        <Button
                            variant="secondary"
                            onClick={() => handleExport('csv')}
                            loading={exporting === 'csv'}
                            disabled={exporting !== null && exporting !== 'csv'}
                        >
                            Export CSV
                        </Button>
                        <Button
                            variant="secondary"
                            onClick={() => handleExport('xlsx')}
                            loading={exporting === 'xlsx'}
                            disabled={
                                exporting !== null && exporting !== 'xlsx'
                            }
                        >
                            Export Excel
                        </Button>
                    </div>
                </div>
                <div className="mt-4 flex flex-wrap items-end gap-3">
                    <Input
                        placeholder="Search guest name or mobile"
                        className="w-64"
                        aria-label="Search analytics events"
                        onChange={(e) => debouncedSearch(e.target.value)}
                    />
                    <Select
                        className="w-52"
                        placeholder="All event types"
                        aria-label="Filter by event type"
                        options={EVENT_OPTIONS}
                        value={event}
                        onChange={(e) =>
                            setEvent(e.target.value as AnalyticsEventName | '')
                        }
                    />
                </div>
            </CardHeader>
            <CardContent className="p-0">
                <Table>
                    <TableHead>
                        <tr>
                            <TableHeaderCell>Occurred at</TableHeaderCell>
                            <TableHeaderCell>Event</TableHeaderCell>
                            <TableHeaderCell>Guest</TableHeaderCell>
                            <TableHeaderCell>Mobile</TableHeaderCell>
                            <TableHeaderCell>Session</TableHeaderCell>
                            <TableHeaderCell>UTM source</TableHeaderCell>
                            <TableHeaderCell>UTM campaign</TableHeaderCell>
                            <TableHeaderCell>Details</TableHeaderCell>
                        </tr>
                    </TableHead>
                    <TableBody>
                        {loading ? (
                            <tr>
                                <TableCell colSpan={8}>
                                    <div className="flex justify-center py-10">
                                        <Spinner className="h-5 w-5 text-(--color-accent)" />
                                    </div>
                                </TableCell>
                            </tr>
                        ) : events.length === 0 ? (
                            <TableEmpty
                                colSpan={8}
                                message="No analytics events match these filters."
                            />
                        ) : (
                            events.map((item) => (
                                <TableRow key={item.id}>
                                    <TableCell className="whitespace-nowrap">
                                        {formatDate(item.occurred_at)}
                                    </TableCell>
                                    <TableCell className="font-medium">
                                        {eventLabel(item.event)}
                                    </TableCell>
                                    <TableCell>
                                        {item.guest.name ?? '—'}
                                    </TableCell>
                                    <TableCell>
                                        {item.guest.mobile ?? '—'}
                                    </TableCell>
                                    <TableCell>
                                        {item.session_id ?? '—'}
                                    </TableCell>
                                    <TableCell>
                                        {item.utm.source ?? '—'}
                                    </TableCell>
                                    <TableCell>
                                        {item.utm.campaign ?? '—'}
                                    </TableCell>
                                    <TableCell>
                                        <details className="max-w-64">
                                            <summary className="cursor-pointer text-(--color-accent)">
                                                View payload
                                            </summary>
                                            <pre className="mt-2 max-h-40 overflow-auto text-xs whitespace-pre-wrap text-(--color-ink-muted)">
                                                {payloadSummary(item)}
                                            </pre>
                                        </details>
                                    </TableCell>
                                </TableRow>
                            ))
                        )}
                    </TableBody>
                </Table>
                <Pagination
                    page={meta.page}
                    lastPage={meta.lastPage}
                    total={meta.total}
                    perPage={meta.perPage}
                    onPageChange={load}
                />
            </CardContent>
        </Card>
    );
}
