'use client';

import { useEffect, useRef, useState } from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { BvasReport2 as Report, BvasReport2Page, isBvasReport2, isBvasReport2Page, turnoutCategory } from '@/lib/bvasReport2';
import { isBvasImage, validateBvasQuery } from '@/lib/bvasInfo';
import { EMPTY_GEOGRAPHY, GeographySelection, geographyFilterQuery } from '@/lib/geography';
import { isRecord } from '@/lib/users';
import { GeographyFilterCards } from './GeographyFields';
import { BvasReportTable, BvasReportDeleteDialog, BvasReportDetailsModal, reportButton as button, reportInput as input } from './BvasReportPresentation';

function message(error: unknown) { return error instanceof Error ? error.message : 'Unable to reach the BVAS Report 2 service.'; }

async function request(url: string, options: RequestInit = {}) {
  const response = await fetch(url, { ...options, cache: 'no-store' });
  if (response.status === 401) window.location.replace('/?screen=get_started');
  if (response.status === 204 && options.method === 'DELETE') return null;
  const data: unknown = await response.json();
  if (!response.ok) {
    const errors = isRecord(data) && isRecord(data.errors) ? Object.entries(data.errors).flatMap(([field, values]) =>
      Array.isArray(values) ? values.filter((value): value is string => typeof value === 'string').map((value) => `${field}: ${value}`) : []) : [];
    throw new Error(errors.length ? errors.join(' ') : isRecord(data) && typeof data.error === 'string' ? data.error : 'The BVAS Report 2 request failed.');
  }
  return data;
}

export function BvasReport2(props: { canDelete: boolean; canFilterGeography: boolean }) {
  const [client] = useState(() => new QueryClient());
  return <QueryClientProvider client={client}><ReportContent {...props} /></QueryClientProvider>;
}

function ReportContent({ canDelete, canFilterGeography }: { canDelete: boolean; canFilterGeography: boolean }) {
  const [geography, setGeography] = useState<GeographySelection>({ ...EMPTY_GEOGRAPHY });
  const [filters, setFilters] = useState('');
  const [filterError, setFilterError] = useState('');
  const [page, setPage] = useState(1);
  const [perPage, setPerPage] = useState(25);
  const [revision, setRevision] = useState(0);
  const [data, setData] = useState<BvasReport2Page | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [detailId, setDetailId] = useState<string | null>(null);
  const [detail, setDetail] = useState<Report | null>(null);
  const [detailError, setDetailError] = useState('');
  const [detailRevision, setDetailRevision] = useState(0);
  const [imageFailed, setImageFailed] = useState(false);
  const [deleting, setDeleting] = useState<Report | null>(null);
  const [busy, setBusy] = useState(false);
  const inFlight = useRef(false);
  const [deleteError, setDeleteError] = useState('');
  const [notice, setNotice] = useState('');

  useEffect(() => {
    const controller = new AbortController();
    setLoading(true); setError(''); setData(null);
    request(`/api/bvas-report-2?${filters}${filters ? '&' : ''}page=${page}&per_page=${perPage}`, { signal: controller.signal })
      .then((value) => {
        if (!isBvasReport2Page(value)) throw new Error('The BVAS Report 2 service returned an invalid list.');
        if (!controller.signal.aborted) setData(value);
      }).catch((error) => { if (!controller.signal.aborted) setError(message(error)); })
      .finally(() => { if (!controller.signal.aborted) setLoading(false); });
    return () => controller.abort();
  }, [filters, page, perPage, revision]);

  useEffect(() => {
    setDetail(null); setDetailError(''); setImageFailed(false);
    if (!detailId) return;
    const controller = new AbortController();
    request(`/api/bvas-report-2/${encodeURIComponent(detailId)}`, { signal: controller.signal })
      .then((value) => {
        if (!isRecord(value) || !isBvasReport2(value.data)) throw new Error('The BVAS Report 2 service returned invalid details.');
        if (!controller.signal.aborted) setDetail(value.data);
      }).catch((error) => { if (!controller.signal.aborted) setDetailError(message(error)); });
    return () => controller.abort();
  }, [detailId, detailRevision]);

  const remove = async (confirmation: string) => {
    if (!canDelete || !deleting || confirmation !== 'delete' || inFlight.current) return;
    inFlight.current = true; setBusy(true); setDeleteError(''); setNotice('');
    try {
      await request(`/api/bvas-report-2/${encodeURIComponent(deleting.id)}`, { method: 'DELETE' });
      if (detailId === deleting.id) setDetailId(null);
      setDeleting(null); setNotice('BVAS Report 2 removed from active records. The backend retains the report and image.');
      if (page > 1 && data?.data.length === 1) setPage(page - 1);
      else setRevision((n) => n + 1);
    } catch (error) { setDeleteError(message(error)); }
    finally { inFlight.current = false; setBusy(false); }
  };

  const formatTime = (value: string) => {
    const date = new Date(value);
    return Number.isNaN(date.getTime()) ? value : date.toLocaleString();
  };

  return <section aria-labelledby="bvas-report-2-heading" className="space-y-6 font-sans text-slate-900">
    {canFilterGeography && <GeographyFilterCards subject="Turn Out" value={geography} onChange={(next) => {
      setGeography(next);
      const query = geographyFilterQuery(next);
      const errors = validateBvasQuery(query, true);
      setFilterError(Object.values(errors).flat().join(' '));
      if (Object.keys(errors).length) return;
      setFilters(query.toString()); setPage(1); setDetailId(null); setDeleting(null);
    }} />}
    <header className="flex flex-wrap items-center justify-between gap-3">
      <div><h1 id="bvas-report-2-heading" className="text-2xl font-bold">Turn Out</h1><p className="mt-1 text-sm text-slate-600">Turnout reports within your assigned geography.</p></div>
      <button className={button} disabled={loading || busy} onClick={() => setRevision((n) => n + 1)}>Refresh</button>
    </header>
    {notice && <p role="status" className="rounded-lg bg-emerald-50 p-3 text-emerald-900">{notice}</p>}
    {filterError && <p role="alert" className="text-rose-700">{filterError}</p>}
    {canDelete && deleting && <BvasReportDeleteDialog key={deleting.id} report={deleting} title="Turn Out report" prerequisite="A replacement requires an active BVAS Default report." busy={busy} error={deleteError} onCancel={() => setDeleting(null)} onConfirm={remove} />}
    {detailId && <BvasReportDetailsModal title="Turnout report details" onClose={() => setDetailId(null)}>
      {detailError ? <p role="alert" className="text-rose-700">{detailError} <button className={button} onClick={() => setDetailRevision((n) => n + 1)}>Retry details</button></p> : !detail ? <p role="status">Loading details...</p> : <>
        <dl className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
          {[
            ['Geozone', detail.geozone_id], ['State', detail.state_id], ['LGA', detail.lga_id],
            ['Ward', detail.ward_id], ['Polling unit', detail.pu_id], ['Time', formatTime(detail.time)],
            ['Turnout category', `${turnoutCategory(detail.percentage)} (${detail.percentage})`], ['Updated at', formatTime(detail.updated_at)],
          ].map(([label, value]) => <div key={label}><dt className="text-sm text-slate-600">{label}</dt><dd className="break-words font-medium">{value || 'Not available'}</dd></div>)}
        </dl>
        <div><h3 className="font-bold">Note</h3><p className="mt-1 whitespace-pre-wrap text-sm text-slate-700">{detail.note || 'No note provided.'}</p></div>
        {!detail.image ? <p className="text-sm text-slate-600">Supporting image is unavailable.</p> :
          imageFailed || !isBvasImage(detail.image) ? <p role="alert" className="text-rose-700">Unable to display the supporting image. <button className={button} onClick={() => setDetailRevision((n) => n + 1)}>Reload details</button></p> :
            <img src={detail.image} alt="Supporting turnout report image" className="max-h-[600px] max-w-full rounded-lg object-contain" onError={() => setImageFailed(true)} />}
      </>}
    </BvasReportDetailsModal>}
    {error && <p role="alert" className="text-rose-700">{error} <button className={button} onClick={() => setRevision((n) => n + 1)}>Retry list</button></p>}
    <BvasReportTable title="Turnout reports" data={data?.data} total={data?.meta.total} loading={loading} selectedId={detailId} canDelete={canDelete} busy={busy} onView={setDetailId} onDelete={(record) => { setDeleting(record); setDeleteError(''); }}
      columns={[{ label: 'Turnout', render: (record) => <span className="rounded-full bg-emerald-50 px-2 py-1 font-medium text-emerald-800">{turnoutCategory(record.percentage)} ({record.percentage})</span> }, { label: 'Time', render: (record) => formatTime(record.time) }, { label: 'Note', render: (record) => <p className="line-clamp-2" title={record.note || ''}>{record.note || 'No note'}</p> }]} />
    <footer className="flex flex-wrap items-center justify-between gap-3 text-sm">
      <label className="flex items-center gap-2">Records per page<select className={input} value={perPage} onChange={(event) => { setPerPage(Number(event.target.value)); setPage(1); }}>{[10, 25, 50, 100].map((n) => <option key={n} value={n}>{n}</option>)}</select></label>
      {data && <div className="flex items-center gap-3"><button className={button} disabled={page <= 1 || loading} onClick={() => setPage(page - 1)}>Previous</button><span>Page {data.meta.current_page} of {data.meta.last_page} ({data.meta.total} records)</span><button className={button} disabled={page >= data.meta.last_page || loading} onClick={() => setPage(page + 1)}>Next</button></div>}
    </footer>
  </section>;
}
