import { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Group, Select, Stack, ThemeIcon } from '@mantine/core';
import { IconCalendarEvent } from '@tabler/icons-react';
import { AmharicDatePicker, AdvancedTable, PageHeader, notify, useServerTable } from '@ema-platform/ui';
import {
  extractErrorMessage,
  useCheckInPickupMutation,
  useGetPickupOfficesQuery,
  useGetPickupWorklistQuery,
  useIssueCertificateMutation,
  useMarkPickupIssuedMutation,
  useMarkPickupNoShowMutation,
  type PickupAppointment,
} from '@ema-platform/api';
import { pickupDeskActionsColumn } from './actions';
import { pickupDeskColumns } from './columns';

function todayIso(): string {
  return new Date().toISOString().slice(0, 10);
}

/**
 * The pickup officer's worklist for one day (spec §43): who is booked, when,
 * and where they are in the visit. Check-in and no-show are pickup-desk
 * concerns; Issue calls the existing certificate-issuance endpoint and then
 * marks the appointment issued, so the two stay in the same state a
 * `SCHEDULED` application has always moved through.
 */
export function PickupDeskPage() {
  const { t } = useTranslation();
  const [date, setDate] = useState(todayIso());
  const [officeId, setOfficeId] = useState<string | null>(null);
  const [loadingId, setLoadingId] = useState<string | null>(null);
  const { setPageIndex, pageSize, setPageSize, paginate } = useServerTable();

  const { data: offices } = useGetPickupOfficesQuery();
  const {
    data: appointments,
    isFetching,
    refetch,
  } = useGetPickupWorklistQuery({ date, officeId: officeId ?? undefined });

  const [checkIn] = useCheckInPickupMutation();
  const [markIssued] = useMarkPickupIssuedMutation();
  const [markNoShow] = useMarkPickupNoShowMutation();
  const [issueCertificate] = useIssueCertificateMutation();

  const officesById = useMemo(
    () => new Map((offices ?? []).map((o) => [o.id, o])),
    [offices],
  );
  const officeOptions = useMemo(
    () => (offices ?? []).map((o) => ({ value: o.id, label: o.name })),
    [offices],
  );

  const rows = [...(appointments ?? [])].sort((a, b) =>
    a.slotStartTime.localeCompare(b.slotStartTime),
  );
  const page = paginate(rows);

  async function withLoading(id: string, action: () => Promise<unknown>) {
    setLoadingId(id);
    try {
      await action();
    } catch (err) {
      notify.error(extractErrorMessage(err), t('pickupDesk.actionFailed', 'Action failed'));
    } finally {
      setLoadingId(null);
    }
  }

  async function handleCheckIn(appointment: PickupAppointment) {
    await withLoading(appointment.id, () => checkIn(appointment.id).unwrap());
  }

  async function handleIssue(appointment: PickupAppointment) {
    await withLoading(appointment.id, async () => {
      // Renders and stores the certificate — the same action a raw
      // schedule-only application reaches from the review page.
      await issueCertificate(appointment.applicationId).unwrap();
      await markIssued(appointment.id).unwrap();
      notify.success(t('pickupDesk.issued', 'Document issued'));
    });
  }

  async function handleNoShow(appointment: PickupAppointment) {
    await withLoading(appointment.id, () => markNoShow(appointment.id).unwrap());
  }

  const columns = [
    ...pickupDeskColumns(t, officesById),
    pickupDeskActionsColumn(
      t,
      { onCheckIn: handleCheckIn, onIssue: handleIssue, onNoShow: handleNoShow },
      loadingId,
    ),
  ];

  return (
    <Stack gap="lg">
      <PageHeader
        title={t('pickupDesk.title', 'Pickup Desk')}
        subtitle={t(
          'pickupDesk.subtitle',
          "Today's and upcoming document pickup appointments.",
        )}
        noMargin
        action={
          <ThemeIcon size="xl" radius="md" variant="light">
            <IconCalendarEvent size={22} />
          </ThemeIcon>
        }
      />

      <Group gap="sm">
        <AmharicDatePicker
          label={t('pickupDesk.date', 'Date')}
          value={date}
          onChange={setDate}
        />
        <Select
          label={t('pickupDesk.office', 'Office')}
          placeholder={t('pickupDesk.allOffices', 'All offices')}
          data={officeOptions}
          value={officeId}
          onChange={setOfficeId}
          clearable
        />
      </Group>

      <AdvancedTable
        tableName="pickup-desk-appointments"
        columns={columns}
        data={page.rows}
        itemCount={page.itemCount}
        pageIndex={page.pageIndex}
        onPageChange={setPageIndex}
        pageSize={pageSize}
        onPageSizeChange={setPageSize}
        refresh={refetch}
        isLoading={isFetching}
        emptyText={t('pickupDesk.empty', 'No appointments for this day.')}
      />
    </Stack>
  );
}

export default PickupDeskPage;
