import {
  ActionIcon,
  Alert,
  Anchor,
  Badge,
  Button,
  Card,
  FileButton,
  Group,
  Loader,
  Modal,
  NumberInput,
  Paper,
  Select,
  Stack,
  Tabs,
  Text,
  TextInput,
  Textarea,
  Title,
  Tooltip,
} from '@mantine/core';
import {
  IconAnchor,
  IconEdit,
  IconFileUpload,
  IconInfoCircle,
  IconPaperclip,
  IconPlus,
  IconStethoscope,
  IconTrash,
} from '@tabler/icons-react';
import { useState } from 'react';
import { AdvancedTable, AmharicDatePicker, notify, useServerTable, type AdvancedColumn } from '@ema-platform/ui';
import { useDateDisplayer } from '@ema-platform/shared';
import {
  extractErrorMessage,
  uploadDocument,
  useCreateMedicalCertificateMutation,
  useCreateSeaServiceRecordMutation,
  useDeleteMedicalCertificateMutation,
  useDeleteSeaServiceRecordMutation,
  useGetAttachmentsQuery,
  useGetMyMedicalCertificatesQuery,
  useGetMySeaServiceRecordsQuery,
  useGetMySeaTimeQuery,
  useUpdateMedicalCertificateMutation,
  useUpdateSeaServiceRecordMutation,
} from '@ema-platform/api';
import type { MedicalCertificate, SeaServiceRecord } from '@ema-platform/api';

const RECORD_STATUS_COLORS: Record<string, string> = {
  SUBMITTED: 'blue',
  VERIFIED: 'green',
  REJECTED: 'red',
};

const FITNESS_OPTIONS = [
  { value: 'FIT', label: 'Fit' },
  { value: 'FIT_WITH_RESTRICTIONS', label: 'Fit with restrictions' },
  { value: 'UNFIT', label: 'Unfit' },
];

/**
 * Evidence viewer/uploader shared by both record kinds.
 *
 * Files upload against the record itself (`SEA_SERVICE_RECORD` /
 * `MEDICAL_CERTIFICATE` owner types), so the officer verifying it later opens
 * exactly what the seafarer attached.
 */
function EvidenceModal({
  ownerType,
  ownerId,
  onClose,
}: {
  ownerType: 'SEA_SERVICE_RECORD' | 'MEDICAL_CERTIFICATE';
  ownerId: string | null;
  onClose: () => void;
}) {
  const { data: attachments, refetch, isLoading } = useGetAttachmentsQuery(
    { ownerType, ownerId: ownerId ?? '' },
    { skip: !ownerId },
  );
  const [uploading, setUploading] = useState(false);

  const upload = async (file: File | null) => {
    if (!file || !ownerId) return;
    setUploading(true);
    const result = await uploadDocument({
      ownerType,
      ownerId,
      documentKey: 'evidence',
      file,
    });
    setUploading(false);
    if (result.ok) {
      notify.success('Evidence uploaded');
      refetch();
    } else {
      notify.error(result.error);
    }
  };

  const files = (attachments ?? []).flatMap((a) => a.files);

  return (
    <Modal opened={Boolean(ownerId)} onClose={onClose} title="Evidence" centered>
      <Stack>
        {isLoading ? (
          <Loader size="sm" />
        ) : files.length === 0 ? (
          <Text size="sm" c="dimmed">
            No evidence uploaded yet.
          </Text>
        ) : (
          files.map((file) => (
            <Group key={file.id} gap="xs">
              <IconPaperclip size={16} />
              {file.url ? (
                <Anchor href={file.url} target="_blank" size="sm">
                  {file.originalName}
                </Anchor>
              ) : (
                <Text size="sm">{file.originalName}</Text>
              )}
            </Group>
          ))
        )}
        <FileButton onChange={upload} accept="image/*,application/pdf">
          {(props) => (
            <Button
              {...props}
              variant="light"
              loading={uploading}
              leftSection={<IconFileUpload size={16} />}
            >
              Upload evidence
            </Button>
          )}
        </FileButton>
      </Stack>
    </Modal>
  );
}

// ---------------------------------------------------------------- sea service

const EMPTY_SEA_SERVICE = {
  vesselName: '',
  imoNumber: '',
  vesselType: '',
  flagState: '',
  rank: '',
  engagementDate: '',
  dischargeDate: '',
  dutiesDescription: '',
};

function SeaServiceTab() {
  const showDate = useDateDisplayer();
  const { data: records, isLoading, refetch } = useGetMySeaServiceRecordsQuery();
  const { data: seaTime } = useGetMySeaTimeQuery();
  const [createRecord, { isLoading: creating }] =
    useCreateSeaServiceRecordMutation();
  const [updateRecord, { isLoading: updating }] =
    useUpdateSeaServiceRecordMutation();
  const [deleteRecord] = useDeleteSeaServiceRecordMutation();

  const [editing, setEditing] = useState<SeaServiceRecord | null>(null);
  const [modalOpen, setModalOpen] = useState(false);
  const [evidenceFor, setEvidenceFor] = useState<string | null>(null);
  const [form, setForm] = useState(EMPTY_SEA_SERVICE);
  const [grossTonnage, setGrossTonnage] = useState<number | ''>('');

  const openCreate = () => {
    setEditing(null);
    setForm(EMPTY_SEA_SERVICE);
    setGrossTonnage('');
    setModalOpen(true);
  };

  const openEdit = (record: SeaServiceRecord) => {
    setEditing(record);
    setForm({
      vesselName: record.vesselName,
      imoNumber: record.imoNumber ?? '',
      vesselType: record.vesselType ?? '',
      flagState: record.flagState ?? '',
      rank: record.rank,
      engagementDate: record.engagementDate,
      dischargeDate: record.dischargeDate,
      dutiesDescription: record.dutiesDescription ?? '',
    });
    setGrossTonnage(record.grossTonnage ? Number(record.grossTonnage) : '');
    setModalOpen(true);
  };

  const save = async () => {
    const body = {
      vesselName: form.vesselName,
      rank: form.rank,
      engagementDate: form.engagementDate,
      dischargeDate: form.dischargeDate,
      ...(form.imoNumber ? { imoNumber: form.imoNumber } : {}),
      ...(form.vesselType ? { vesselType: form.vesselType } : {}),
      ...(form.flagState ? { flagState: form.flagState } : {}),
      ...(form.dutiesDescription
        ? { dutiesDescription: form.dutiesDescription }
        : {}),
      ...(grossTonnage !== '' ? { grossTonnage: Number(grossTonnage) } : {}),
    };
    try {
      if (editing) {
        await updateRecord({ id: editing.id, body }).unwrap();
        notify.success('Sea-service record updated');
      } else {
        await createRecord(body).unwrap();
        notify.success('Sea-service record added');
      }
      setModalOpen(false);
    } catch (error) {
      notify.error(extractErrorMessage(error, 'Could not save the record'));
    }
  };

  const remove = async (record: SeaServiceRecord) => {
    try {
      await deleteRecord(record.id).unwrap();
      notify.success('Record withdrawn');
    } catch (error) {
      notify.error(extractErrorMessage(error, 'Could not delete the record'));
    }
  };

  const valid =
    form.vesselName.trim().length > 1 &&
    form.rank.trim().length > 1 &&
    form.engagementDate &&
    form.dischargeDate &&
    form.engagementDate < form.dischargeDate;

  const { setPageIndex, pageSize, setPageSize, paginate } = useServerTable({ pageSize: 10 });
  const page = paginate(records ?? []);

  const columns: AdvancedColumn<SeaServiceRecord>[] = [
    {
      header: 'Vessel',
      cell: ({ row }) => (
        <>
          <Text fw={600} size="sm">
            {row.original.vesselName}
          </Text>
          {row.original.imoNumber && (
            <Text size="xs" c="dimmed">
              IMO {row.original.imoNumber}
            </Text>
          )}
        </>
      ),
    },
    { header: 'Rank', accessorKey: 'rank' },
    {
      header: 'From',
      accessorKey: 'engagementDate',
      cell: ({ row }) => showDate(row.original.engagementDate),
    },
    {
      header: 'To',
      accessorKey: 'dischargeDate',
      cell: ({ row }) => showDate(row.original.dischargeDate),
    },
    {
      header: 'Status',
      cell: ({ row }) => (
        <Tooltip
          label={row.original.verificationRemark ?? ''}
          disabled={!row.original.verificationRemark}
        >
          <Badge color={RECORD_STATUS_COLORS[row.original.status]}>
            {row.original.status}
          </Badge>
        </Tooltip>
      ),
    },
    {
      header: '',
      label: 'Actions',
      align: 'right',
      cell: ({ row }) => {
        const record = row.original;
        const locked = record.status !== 'SUBMITTED';
        return (
          <Group gap="xs" justify="flex-end" wrap="nowrap">
            <Tooltip label="Evidence">
              <ActionIcon
                variant="subtle"
                onClick={() => setEvidenceFor(record.id)}
              >
                <IconPaperclip size={16} />
              </ActionIcon>
            </Tooltip>
            <Tooltip label={locked ? 'Verified records are frozen' : 'Edit'}>
              <ActionIcon
                variant="subtle"
                disabled={locked}
                onClick={() => openEdit(record)}
              >
                <IconEdit size={16} />
              </ActionIcon>
            </Tooltip>
            <Tooltip label={locked ? 'Verified records are frozen' : 'Delete'}>
              <ActionIcon
                variant="subtle"
                color="red"
                disabled={locked}
                onClick={() => remove(record)}
              >
                <IconTrash size={16} />
              </ActionIcon>
            </Tooltip>
          </Group>
        );
      },
    },
  ];

  return (
    <Stack>
      <Group justify="space-between">
        <Group gap="sm">
          <Text size="sm" c="dimmed">
            Every engagement aboard a vessel, with its evidence. Verified
            records feed certificate eligibility.
          </Text>
          {seaTime && seaTime.verifiedRecords > 0 && (
            <Badge variant="light" color="teal">
              Approved sea time: {seaTime.totalDays} days
            </Badge>
          )}
        </Group>
        <Button leftSection={<IconPlus size={16} />} onClick={openCreate}>
          Add sea service
        </Button>
      </Group>
      {(records ?? []).length === 0 ? (
        <Paper withBorder p="xl" radius="md">
          <Text c="dimmed" ta="center">
            No sea-service records yet.
          </Text>
        </Paper>
      ) : (
        <Card withBorder padding={0}>
          <AdvancedTable
            columns={columns}
            data={page.rows}
            tableName="Sea service"
            itemCount={page.itemCount}
            pageIndex={page.pageIndex}
            onPageChange={setPageIndex}
            pageSize={pageSize}
            onPageSizeChange={setPageSize}
            isLoading={isLoading}
            refresh={refetch}
          />
        </Card>
      )}

      <Modal
        opened={modalOpen}
        onClose={() => setModalOpen(false)}
        title={editing ? 'Edit sea service' : 'Add sea service'}
        centered
        size="lg"
      >
        <Stack>
          <Group grow>
            <TextInput
              label="Vessel name"
              required
              value={form.vesselName}
              onChange={(e) => setForm({ ...form, vesselName: e.target.value })}
            />
            <TextInput
              label="IMO number"
              value={form.imoNumber}
              onChange={(e) => setForm({ ...form, imoNumber: e.target.value })}
            />
          </Group>
          <Group grow>
            <TextInput
              label="Vessel type"
              value={form.vesselType}
              onChange={(e) => setForm({ ...form, vesselType: e.target.value })}
            />
            <TextInput
              label="Flag state"
              value={form.flagState}
              onChange={(e) => setForm({ ...form, flagState: e.target.value })}
            />
            <NumberInput
              label="Gross tonnage"
              min={0}
              value={grossTonnage}
              onChange={(v) => setGrossTonnage(typeof v === 'number' ? v : '')}
            />
          </Group>
          <TextInput
            label="Rank / capacity"
            required
            value={form.rank}
            onChange={(e) => setForm({ ...form, rank: e.target.value })}
          />
          <Group grow>
            <AmharicDatePicker
              label="Engagement date"
              required
              value={form.engagementDate}
              onChange={(val) =>
                setForm({ ...form, engagementDate: val })
              }
              dateFormat="date"
            />
            <AmharicDatePicker
              label="Discharge date"
              required
              value={form.dischargeDate}
              onChange={(val) =>
                setForm({ ...form, dischargeDate: val })
              }
              dateFormat="date"
            />
          </Group>
          <Textarea
            label="Duties"
            value={form.dutiesDescription}
            onChange={(e) =>
              setForm({ ...form, dutiesDescription: e.target.value })
            }
          />
          <Group justify="flex-end">
            <Button variant="default" onClick={() => setModalOpen(false)}>
              Cancel
            </Button>
            <Button
              onClick={save}
              disabled={!valid}
              loading={creating || updating}
            >
              {editing ? 'Save changes' : 'Add record'}
            </Button>
          </Group>
        </Stack>
      </Modal>

      <EvidenceModal
        ownerType="SEA_SERVICE_RECORD"
        ownerId={evidenceFor}
        onClose={() => setEvidenceFor(null)}
      />
    </Stack>
  );
}

// -------------------------------------------------------------------- medical

const EMPTY_MEDICAL = {
  issuerName: '',
  certificateNumber: '',
  issueDate: '',
  expiryDate: '',
  fitnessStatus: 'FIT',
  restrictions: '',
};

function MedicalTab() {
  const showDate = useDateDisplayer();
  const { data: certificates, isLoading, refetch } = useGetMyMedicalCertificatesQuery();
  const [createCertificate, { isLoading: creating }] =
    useCreateMedicalCertificateMutation();
  const [updateCertificate, { isLoading: updating }] =
    useUpdateMedicalCertificateMutation();
  const [deleteCertificate] = useDeleteMedicalCertificateMutation();

  const [editing, setEditing] = useState<MedicalCertificate | null>(null);
  const [modalOpen, setModalOpen] = useState(false);
  const [evidenceFor, setEvidenceFor] = useState<string | null>(null);
  const [form, setForm] = useState(EMPTY_MEDICAL);

  const openCreate = () => {
    setEditing(null);
    setForm(EMPTY_MEDICAL);
    setModalOpen(true);
  };

  const openEdit = (certificate: MedicalCertificate) => {
    setEditing(certificate);
    setForm({
      issuerName: certificate.issuerName,
      certificateNumber: certificate.certificateNumber ?? '',
      issueDate: certificate.issueDate,
      expiryDate: certificate.expiryDate,
      fitnessStatus: certificate.fitnessStatus,
      restrictions: certificate.restrictions ?? '',
    });
    setModalOpen(true);
  };

  const save = async () => {
    const body = {
      issuerName: form.issuerName,
      issueDate: form.issueDate,
      expiryDate: form.expiryDate,
      fitnessStatus: form.fitnessStatus as MedicalCertificate['fitnessStatus'],
      ...(form.certificateNumber
        ? { certificateNumber: form.certificateNumber }
        : {}),
      ...(form.restrictions ? { restrictions: form.restrictions } : {}),
    };
    try {
      if (editing) {
        await updateCertificate({ id: editing.id, body }).unwrap();
        notify.success('Medical certificate updated');
      } else {
        await createCertificate(body).unwrap();
        notify.success('Medical certificate added');
      }
      setModalOpen(false);
    } catch (error) {
      notify.error(extractErrorMessage(error, 'Could not save the certificate'));
    }
  };

  const remove = async (certificate: MedicalCertificate) => {
    try {
      await deleteCertificate(certificate.id).unwrap();
      notify.success('Certificate withdrawn');
    } catch (error) {
      notify.error(
        extractErrorMessage(error, 'Could not delete the certificate'),
      );
    }
  };

  const valid =
    form.issuerName.trim().length > 1 &&
    form.issueDate &&
    form.expiryDate &&
    form.issueDate < form.expiryDate;

  const today = new Date().toISOString().slice(0, 10);

  const { setPageIndex, pageSize, setPageSize, paginate } = useServerTable({ pageSize: 10 });
  const page = paginate(certificates ?? []);

  const columns: AdvancedColumn<MedicalCertificate>[] = [
    {
      header: 'Issuer',
      cell: ({ row }) => (
        <>
          <Text fw={600} size="sm">
            {row.original.issuerName}
          </Text>
          {row.original.certificateNumber && (
            <Text size="xs" c="dimmed">
              № {row.original.certificateNumber}
            </Text>
          )}
        </>
      ),
    },
    {
      header: 'Issued',
      accessorKey: 'issueDate',
      cell: ({ row }) => showDate(row.original.issueDate),
    },
    {
      header: 'Expires',
      cell: ({ row }) => (
        <Group gap={6} wrap="nowrap">
          {showDate(row.original.expiryDate)}
          {row.original.expiryDate < today && <Badge color="red">Expired</Badge>}
        </Group>
      ),
    },
    {
      header: 'Fitness',
      cell: ({ row }) =>
        FITNESS_OPTIONS.find((o) => o.value === row.original.fitnessStatus)
          ?.label ?? row.original.fitnessStatus,
    },
    {
      header: 'Status',
      cell: ({ row }) => (
        <Tooltip
          label={row.original.verificationRemark ?? ''}
          disabled={!row.original.verificationRemark}
        >
          <Badge color={RECORD_STATUS_COLORS[row.original.status]}>
            {row.original.status}
          </Badge>
        </Tooltip>
      ),
    },
    {
      header: '',
      label: 'Actions',
      align: 'right',
      cell: ({ row }) => {
        const certificate = row.original;
        const locked = certificate.status !== 'SUBMITTED';
        return (
          <Group gap="xs" justify="flex-end" wrap="nowrap">
            <Tooltip label="Scan / evidence">
              <ActionIcon
                variant="subtle"
                onClick={() => setEvidenceFor(certificate.id)}
              >
                <IconPaperclip size={16} />
              </ActionIcon>
            </Tooltip>
            <Tooltip label={locked ? 'Verified certificates are frozen' : 'Edit'}>
              <ActionIcon
                variant="subtle"
                disabled={locked}
                onClick={() => openEdit(certificate)}
              >
                <IconEdit size={16} />
              </ActionIcon>
            </Tooltip>
            <Tooltip label={locked ? 'Verified certificates are frozen' : 'Delete'}>
              <ActionIcon
                variant="subtle"
                color="red"
                disabled={locked}
                onClick={() => remove(certificate)}
              >
                <IconTrash size={16} />
              </ActionIcon>
            </Tooltip>
          </Group>
        );
      },
    },
  ];

  return (
    <Stack>
      <Group justify="space-between">
        <Text size="sm" c="dimmed">
          STCW medical fitness certificates. An expired certificate blocks new
          applications that require one.
        </Text>
        <Button leftSection={<IconPlus size={16} />} onClick={openCreate}>
          Add certificate
        </Button>
      </Group>
      {(certificates ?? []).length === 0 ? (
        <Paper withBorder p="xl" radius="md">
          <Text c="dimmed" ta="center">
            No medical certificates yet.
          </Text>
        </Paper>
      ) : (
        <Card withBorder padding={0}>
          <AdvancedTable
            columns={columns}
            data={page.rows}
            tableName="Medical certificates"
            itemCount={page.itemCount}
            pageIndex={page.pageIndex}
            onPageChange={setPageIndex}
            pageSize={pageSize}
            onPageSizeChange={setPageSize}
            isLoading={isLoading}
            refresh={refetch}
          />
        </Card>
      )}

      <Modal
        opened={modalOpen}
        onClose={() => setModalOpen(false)}
        title={editing ? 'Edit medical certificate' : 'Add medical certificate'}
        centered
        size="lg"
      >
        <Stack>
          <Group grow>
            <TextInput
              label="Issuing clinic / physician"
              required
              value={form.issuerName}
              onChange={(e) => setForm({ ...form, issuerName: e.target.value })}
            />
            <TextInput
              label="Certificate number"
              value={form.certificateNumber}
              onChange={(e) =>
                setForm({ ...form, certificateNumber: e.target.value })
              }
            />
          </Group>
          <Group grow>
            <AmharicDatePicker
              label="Issue date"
              required
              value={form.issueDate}
              onChange={(val) => setForm({ ...form, issueDate: val })}
              dateFormat="date"
            />
            <AmharicDatePicker
              label="Expiry date"
              required
              value={form.expiryDate}
              onChange={(val) => setForm({ ...form, expiryDate: val })}
              dateFormat="date"
            />
          </Group>
          <Select
            label="Fitness outcome"
            data={FITNESS_OPTIONS}
            value={form.fitnessStatus}
            onChange={(v) => setForm({ ...form, fitnessStatus: v ?? 'FIT' })}
          />
          {form.fitnessStatus === 'FIT_WITH_RESTRICTIONS' && (
            <Textarea
              label="Restrictions"
              value={form.restrictions}
              onChange={(e) =>
                setForm({ ...form, restrictions: e.target.value })
              }
            />
          )}
          <Group justify="flex-end">
            <Button variant="default" onClick={() => setModalOpen(false)}>
              Cancel
            </Button>
            <Button
              onClick={save}
              disabled={!valid}
              loading={creating || updating}
            >
              {editing ? 'Save changes' : 'Add certificate'}
            </Button>
          </Group>
        </Stack>
      </Modal>

      <EvidenceModal
        ownerType="MEDICAL_CERTIFICATE"
        ownerId={evidenceFor}
        onClose={() => setEvidenceFor(null)}
      />
    </Stack>
  );
}

/**
 * The seafarer's evidence shelf (US-SSM-001/006): sea-service history and
 * medical certificates, each with uploaded evidence, editable until an
 * officer verifies them.
 */
export function MySeaRecordsPage() {
  return (
    <Stack>
      <Title order={2}>My Sea Records</Title>
      <Alert
        variant="light"
        color="blue"
        icon={<IconInfoCircle size={16} />}
      >
        Records you add here are submitted for EMA verification. Once verified
        they are frozen and count toward certificate eligibility.
      </Alert>
      <Tabs defaultValue="sea-service" keepMounted={false}>
        <Tabs.List>
          <Tabs.Tab value="sea-service" leftSection={<IconAnchor size={16} />}>
            Sea Service
          </Tabs.Tab>
          <Tabs.Tab value="medical" leftSection={<IconStethoscope size={16} />}>
            Medical Certificates
          </Tabs.Tab>
        </Tabs.List>
        <Tabs.Panel value="sea-service" pt="md">
          <SeaServiceTab />
        </Tabs.Panel>
        <Tabs.Panel value="medical" pt="md">
          <MedicalTab />
        </Tabs.Panel>
      </Tabs>
    </Stack>
  );
}
