import { Badge, Card, Group, SimpleGrid, Text, Tooltip } from '@mantine/core';
import {
  IconAlarm,
  IconAnchor,
  IconCalendarStats,
  IconCoin,
  IconClockHour4,
  IconScale,
  IconShip,
  IconThumbUp,
  type Icon,
} from '@tabler/icons-react';
import type { VesselReport } from '@ema-platform/api';
import {
  DASH,
  deltaColor,
  formatDelta,
  formatMoney,
  formatNumber,
  formatPercent,
} from './report-format';

interface TileProps {
  icon: Icon;
  label: string;
  value: string;
  /** The second line: what the headline figure is made of. */
  detail?: string;
  /** Hover text for anything the headline alone would misrepresent. */
  hint?: string;
  delta?: { text: string; color: string };
  color?: string;
}

function Tile({ icon: TileIcon, label, value, detail, hint, delta, color = 'blue' }: TileProps) {
  const card = (
    <Card withBorder radius="md" p="md">
      <Group justify="space-between" wrap="nowrap" mb={4}>
        <Text size="xs" c="dimmed" fw={600} tt="uppercase" lh={1.3}>
          {label}
        </Text>
        <TileIcon size={18} stroke={1.6} color={`var(--mantine-color-${color}-6)`} />
      </Group>
      <Group gap="xs" align="baseline" wrap="nowrap">
        <Text fz={26} fw={700} lh={1.1}>
          {value}
        </Text>
        {delta && (
          <Badge size="sm" variant="light" color={delta.color}>
            {delta.text}
          </Badge>
        )}
      </Group>
      {detail && (
        <Text size="xs" c="dimmed" mt={6} lh={1.4}>
          {detail}
        </Text>
      )}
    </Card>
  );

  return hint ? (
    <Tooltip label={hint} multiline w={260} withArrow>
      {card}
    </Tooltip>
  ) : (
    card
  );
}

/**
 * The headline figures.
 *
 * Two different scopes sit side by side here and the labels have to keep them
 * apart: the register totals describe the whole book regardless of the date
 * filter, while "new in period" and the pipeline figures answer to it. A tile
 * reading "12 vessels" under a one-month filter would be taken for the size of
 * the national fleet.
 */
export function KpiTiles({ report }: { report: VesselReport }) {
  const { register, fleet, pipeline, certificates, revenue } = report.kpis;

  return (
    <SimpleGrid cols={{ base: 1, xs: 2, md: 4 }} spacing="md">
      <Tile
        icon={IconShip}
        label="Vessels on the register"
        value={formatNumber(register.total)}
        detail={`${formatNumber(register.registered)} registered · ${formatNumber(register.suspended)} suspended · ${formatNumber(register.deregistered)} deregistered`}
        hint="The whole register. Not affected by the date filter."
      />
      <Tile
        icon={IconCalendarStats}
        color="teal"
        label="New in period"
        value={formatNumber(register.registeredInPeriod)}
        detail={`${formatNumber(register.registeredInPreviousPeriod)} in the previous period`}
        delta={{
          text: formatDelta(register.changePct),
          color: deltaColor(register.changePct),
        }}
        hint="Vessels entered on the register inside the selected window, against the equally long window before it."
      />
      <Tile
        icon={IconScale}
        color="indigo"
        label="Fleet tonnage"
        value={formatNumber(fleet.totalGrossTonnage)}
        // The coverage count is not decoration: an average over 2 of 300 hulls
        // is a different claim from an average over all of them.
        detail={`avg ${formatNumber(fleet.avgGrossTonnage, { decimals: 1 })} GT across ${formatNumber(fleet.grossTonnageKnownFor)} of ${formatNumber(register.total)} vessels`}
        hint="Gross tonnage is optional on the register, so the average covers only the vessels that declared one."
      />
      <Tile
        icon={IconAnchor}
        color="cyan"
        label="Average age"
        value={
          fleet.avgAgeYears === null
            ? DASH
            : formatNumber(fleet.avgAgeYears, { decimals: 1, suffix: ' yrs' })
        }
        detail={`${formatNumber(fleet.seaGoing)} sea-going · ${formatNumber(fleet.inlandWaterway)} inland · known for ${formatNumber(fleet.ageKnownFor)}`}
        hint="Derived from the build year, which not every entry carries."
      />
      <Tile
        icon={IconThumbUp}
        color="green"
        label="Approval rate"
        value={formatPercent(pipeline.approvalRatePct)}
        detail={`${formatNumber(pipeline.approved)} approved · ${formatNumber(pipeline.rejected)} rejected · ${formatNumber(pipeline.inProgress)} in flight`}
        hint="Approved as a share of decided applications. Drafts and applications still in the queue are excluded."
      />
      <Tile
        icon={IconClockHour4}
        color="grape"
        label="Processing time"
        value={
          pipeline.medianProcessingDays === null
            ? DASH
            : formatNumber(pipeline.medianProcessingDays, {
                decimals: 1,
                suffix: ' d',
              })
        }
        detail={`median · mean ${formatNumber(pipeline.avgProcessingDays, { decimals: 1, suffix: ' d' })} · ${formatNumber(pipeline.avgAdjustmentRounds, { decimals: 2 })} adjustment rounds`}
        hint="Submission to decision. Only applications that have been decided are counted."
      />
      <Tile
        icon={IconAlarm}
        color="orange"
        label="Certificates expiring"
        value={formatNumber(certificates.expiringIn30)}
        detail={`within 30 days · ${formatNumber(certificates.expiringIn60)} within 60 · ${formatNumber(certificates.expiringIn90)} within 90`}
        hint="Cumulative: a certificate due in a fortnight is counted in all three figures."
      />
      <Tile
        icon={IconCoin}
        color="yellow"
        label="Fees collected"
        value={formatMoney(revenue.paid, revenue.currency)}
        detail={`${formatMoney(revenue.pending, revenue.currency)} outstanding · ${formatNumber(revenue.failedCount)} failed`}
        hint={
          revenue.mixedCurrency
            ? 'The register holds payments in more than one currency; this total sums across them.'
            : undefined
        }
      />
    </SimpleGrid>
  );
}
