import { useNavigate } from 'react-router-dom';
import {
  ActionIcon,
  Badge,
  Box,
  Button,
  Card,
  Divider,
  Group,
  Text,
  Tooltip,
} from '@mantine/core';
import { IconAlertTriangle, IconDownload, IconRefresh } from '@tabler/icons-react';
import {
  extractErrorMessage,
  useLocalized,
  useCreateApplicationMutation,
  type IssuedLicense,
} from '@ema-platform/api';
import { notify } from '@ema-platform/ui';
import { useDateDisplayer } from '@ema-platform/shared';
import { useTranslation } from 'react-i18next';
import {
  LICENSE_PERMISSIONS,
  PORTAL_PERMISSIONS,
  RequirePermission,
} from '@ema-platform/auth';

/**
 * Renewal reuses the ordinary application wizard — a renewal is an
 * application of kind RENEWAL, asking for that licence type's renewal
 * document set. `previousLicenseId` is what ties it to the certificate being
 * replaced, and what the API requires.
 *
 * Shared by the dashboard and My Applications so both offer the same renew
 * action instead of drifting.
 */
export function useRenewLicense() {
  const navigate = useNavigate();
  const { t } = useTranslation();
  const [createApplication, { isLoading: isRenewing }] =
    useCreateApplicationMutation();

  async function renewLicense(license: IssuedLicense) {
    const typeKey = license.licenseType?.key;
    if (!typeKey) return;
    try {
      const application = await createApplication({
        licenseType: typeKey,
        kind: 'RENEWAL',
        previousLicenseId: license.id,
      }).unwrap();
      navigate(`/licensing/${typeKey}/applications/${application.id}`);
    } catch (err) {
      notify.error(extractErrorMessage(err), t('licensing.card.renewFailed'));
    }
  }

  return { renewLicense, isRenewing };
}

/**
 * Damaged/Reissue reuses the same wizard, application kind REISSUE — the
 * "Damage Information" step and the Reissue document set only appear because
 * the created application carries that kind, exactly the way RENEWAL's own
 * fields do above.
 */
export function useReissueLicense() {
  const navigate = useNavigate();
  const { t } = useTranslation();
  const [createApplication, { isLoading: isReissuing }] =
    useCreateApplicationMutation();

  async function reissueLicense(license: IssuedLicense) {
    const typeKey = license.licenseType?.key;
    if (!typeKey) return;
    try {
      const application = await createApplication({
        licenseType: typeKey,
        kind: 'REISSUE',
        previousLicenseId: license.id,
      }).unwrap();
      navigate(`/licensing/${typeKey}/applications/${application.id}`);
    } catch (err) {
      notify.error(extractErrorMessage(err), t('licensing.card.reissueFailed'));
    }
  }

  return { reissueLicense, isReissuing };
}

function daysUntil(date: string): number {
  const ms = new Date(date).getTime() - Date.now();
  return Math.ceil(ms / 86_400_000);
}

export function LicenseCard({
  license,
  isDownloading,
  isRenewing,
  isReissuing,
  onDownload,
  onRenew,
  onReissue,
}: {
  license: IssuedLicense;
  isDownloading: boolean;
  isRenewing: boolean;
  isReissuing?: boolean;
  onDownload: () => void;
  onRenew: () => void;
  onReissue?: () => void;
}) {
  // The API computes both in the authority's timezone; the local fallbacks are
  // only for a cached response from before those fields existed.
  const days = license.daysUntilExpiry ?? daysUntil(license.expiryDate);
  const expired = license.status === 'EXPIRED' || days < 0;
  // Suspended, cancelled and superseded are none of them "valid until" their
  // expiry date — the card used to say exactly that, because only EXPIRED was
  // treated as not-current. A suspended licence read as a live one with a grey
  // badge.
  const current = license.status === 'ACTIVE' && !expired;
  const renewable = license.renewable ?? false;
  const reissuable = license.reissuable ?? false;
  const showDate = useDateDisplayer();
  const localized = useLocalized();
  const { t } = useTranslation();

  return (
    <Card withBorder radius="md" padding="md" className="ema-hover-lift">
      <Group justify="space-between" align="flex-start" wrap="nowrap">
        <Box>
          <Text size="sm" fw={600}>
            {localized(license.licenseType?.name) || t('licensing.card.fallbackName')}
          </Text>
          <Text size="xs" c="dimmed" mt={2}>
            {license.certificateNumber}
          </Text>
        </Box>
        <Badge
          size="sm"
          variant="light"
          color={expired ? 'red' : current ? 'teal' : 'gray'}
        >
          {/* The raw enum was rendered here, so an Amharic page showed
              "SUSPENDED" among otherwise translated text. */}
          {expired
            ? t('licensing.card.expired')
            : t(`licensing.card.status.${license.status}`, {
                defaultValue: license.status,
              })}
        </Badge>
      </Group>

      <Divider my="sm" />

      <Group justify="space-between" align="center">
        <Box>
          <Text size="sm" fw={500}>
            {expired
              ? t('licensing.card.expiredOn', { date: showDate(license.expiryDate) })
              : current
                ? t('licensing.card.validUntil', { date: showDate(license.expiryDate) })
                : t(`licensing.card.status.${license.status}`, {
                    defaultValue: license.status,
                  })}
          </Text>
          {/* Why it stopped being current. The API returns it; the card threw
              it away, leaving the holder to guess. */}
          {!current && license.statusReason && (
            <Text size="xs" c="dimmed" mt={2}>
              {t('licensing.card.statusReason', { reason: license.statusReason })}
            </Text>
          )}
        </Box>
        <RequirePermission
          anyOf={[
            PORTAL_PERMISSIONS.VIEW_OWN_CERTIFICATES,
            PORTAL_PERMISSIONS.VIEW_COMPANY_LICENSES,
          ]}
          hideOnly
        >
          <Tooltip label={t('licensing.card.downloadCertificate')}>
            <ActionIcon
              variant="light"
              radius="md"
              size="lg"
              loading={isDownloading}
              onClick={onDownload}
            >
              <IconDownload size={16} />
            </ActionIcon>
          </Tooltip>
        </RequirePermission>
      </Group>

      {/* Renewal opens inside the licence type's window and stays open after
          expiry, so a lapsed licence is renewed rather than applied for afresh. */}
      {renewable && (
        <RequirePermission anyOf={[LICENSE_PERMISSIONS.CREATE_APPLICATION]} hideOnly>
          <Button
            fullWidth
            mt="sm"
            size="xs"
            variant={expired ? 'filled' : 'light'}
            color={expired ? 'orange' : undefined}
            loading={isRenewing}
            leftSection={<IconRefresh size={14} />}
            onClick={onRenew}
          >
            {expired
              ? t('licensing.card.renewExpired')
              : t('licensing.card.renewDays', { count: days })}
          </Button>
        </RequirePermission>
      )}

      {/* Damaged/Reissue has no window — a lost or damaged document can be
          replaced at any point in its validity, unlike Renewal above. */}
      {reissuable && onReissue && (
        <RequirePermission anyOf={[LICENSE_PERMISSIONS.CREATE_APPLICATION]} hideOnly>
          <Button
            fullWidth
            mt="xs"
            size="xs"
            variant="subtle"
            color="gray"
            loading={isReissuing}
            leftSection={<IconAlertTriangle size={14} />}
            onClick={onReissue}
          >
            {t('licensing.card.reportDamaged')}
          </Button>
        </RequirePermission>
      )}
    </Card>
  );
}

export default LicenseCard;
