import { useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';
import type { TFunction } from 'i18next';
import {
  Alert,
  Anchor,
  Box,
  Button,
  Card,
  Center,
  Container,
  Group,
  Paper,
  SimpleGrid,
  Stack,
  Text,
  ThemeIcon,
  Title,
} from '@mantine/core';
import {
  IconAlertTriangle,
  IconCertificate,
  IconClipboardList,
  IconClockHour4,
  IconCreditCard,
  IconFileText,
  IconShieldCheck,
} from '@tabler/icons-react';
import { ProfileCompletionNudge } from '../../../profile/components/ProfileCompletionNudge';
import {
  APPLICANT_ACTION_STATUSES,
  STATUS_COLORS,
  TERMINAL_STATUSES,
  useGetCertificateUrlMutation,
  useGetMyApplicationsQuery,
  useGetMyLicensesQuery,
} from '@ema-platform/api';
import { AdvancedTable, PageLoader, useServerTable } from '@ema-platform/ui';
import type { IssuedLicense, LicenseApplication } from '@ema-platform/api';
import { LicenseCatalogue } from '../../../licensing/components/LicenseCatalogue';
import { LicenseCard, useRenewLicense } from '../../../licensing/components/LicenseCard';
import { dashboardApplicationColumns } from './columns';

/**
 * The applicant's home screen.
 *
 * Ordered by what the applicant needs from it: first anything blocked on them,
 * then the records they already have — licences, then applications — and only
 * then the catalogue to file something new. A returning applicant comes here to
 * check on their own things, not to shop; the catalogue used to sit above both
 * and pushed them below the fold.
 *
 * The exception is an applicant with nothing at all, for whom both sections are
 * empty and the catalogue *is* the page. Every figure is the signed-in user's
 * own data — there are no illustrative numbers on this page.
 */

/** Days before expiry at which a licence is worth flagging. */
const EXPIRY_WARNING_DAYS = 60;

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

function formatMoney(
  amount: string | number | null,
  currency: string,
  t: TFunction,
): string {
  if (amount === null || amount === '') return t('dashboard.noFee');
  const value = Number(amount);
  if (!Number.isFinite(value)) return t('dashboard.noFee');
  return `${value.toLocaleString('en-US')} ${currency}`;
}

export function DashboardPage() {
  const navigate = useNavigate();
  const { t } = useTranslation();
  const displayName = useSelector(
    (state: { auth: { user?: { name?: { en?: string }; username?: string } } }) =>
      state.auth.user?.name?.en || state.auth.user?.username || '',
  );

  const { data: applications, isLoading, refetch } = useGetMyApplicationsQuery();
  const { data: licenses } = useGetMyLicensesQuery();
  const [getCertificateUrl, { isLoading: isDownloading }] =
    useGetCertificateUrlMutation();
  const { renewLicense, isRenewing } = useRenewLicense();

  const items = useMemo(() => applications?.items ?? [], [applications]);
  const heldLicenses = useMemo(() => licenses?.items ?? [], [licenses]);

  const needsMe = items.filter((a) =>
    APPLICANT_ACTION_STATUSES.includes(a.status),
  );
  const inProgress = items.filter(
    (a) => !TERMINAL_STATUSES.includes(a.status) && a.status !== 'DRAFT',
  );
  const activeLicenses = heldLicenses.filter((l) => l.status === 'ACTIVE');
  // Nothing filed and nothing held: the two "my …" sections would both be
  // empty, so they collapse into one panel and the catalogue carries the page.
  const hasNoRecords = items.length === 0 && heldLicenses.length === 0;
  const expiringSoon = activeLicenses.filter((l) => {
    const days = daysUntil(l.expiryDate);
    return days >= 0 && days <= EXPIRY_WARNING_DAYS;
  });

  async function downloadCertificate(license: IssuedLicense) {
    const result = await getCertificateUrl(license.id).unwrap();
    window.open(result.url, '_blank', 'noopener');
  }

  if (isLoading) {
    return <PageLoader label={t('dashboard.loading')} height={450} />;
  }

  return (
    <Container size="xl" py="lg">
      <Stack gap="xl">
        <Hero
          displayName={displayName}
          applicationCount={items.length}
          licenseCount={activeLicenses.length}
        />

        {/* A prompt, not a gate — dismissible and it never blocks the page. */}
        <ProfileCompletionNudge />

        {needsMe.length > 0 && (
          <ActionRequired applications={needsMe} navigate={navigate} />
        )}

        {expiringSoon.length > 0 && (
          <Alert
            variant="light"
            color="orange"
            radius="md"
            icon={<IconClockHour4 size={18} />}
            title={t('applications.notice.expiringSoon', { count: expiringSoon.length })}
          >
            <Text size="sm">
              {expiringSoon
                .map((l) =>
                  t('dashboard.expiringSoon.detail', {
                    certificateNumber: l.certificateNumber,
                    days: daysUntil(l.expiryDate),
                  }),
                )
                .join(' · ')}
            </Text>
          </Alert>
        )}

        <StatRow
          inProgress={inProgress.length}
          needsMe={needsMe.length}
          activeLicenses={activeLicenses.length}
          expiringSoon={expiringSoon.length}
        />

        {hasNoRecords ? (
          <GetStartedPanel />
        ) : (
          <>
            <Section title={t('dashboard.sections.myLicences.title')}>
              {heldLicenses.length === 0 ? (
                <EmptyCard message={t('applications.licences.empty')} />
              ) : (
                <SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }} spacing="md">
                  {heldLicenses.map((license) => (
                    <LicenseCard
                      key={license.id}
                      license={license}
                      isDownloading={isDownloading}
                      isRenewing={isRenewing}
                      onDownload={() => downloadCertificate(license)}
                      onRenew={() => renewLicense(license)}
                    />
                  ))}
                </SimpleGrid>
              )}
            </Section>

            <Section
              title={t('dashboard.sections.myApplications.title')}
              action={
                items.length > 0 ? (
                  <Anchor
                    size="sm"
                    onClick={() => navigate('/licensing/applications')}
                  >
                    {t('common.viewAll')}
                  </Anchor>
                ) : undefined
              }
            >
              {items.length === 0 ? (
                <EmptyCard message={t('dashboard.sections.myApplications.empty')} />
              ) : (
                <ApplicationTable
                  applications={items.slice(0, 6)}
                  navigate={navigate}
                  onRefresh={refetch}
                />
              )}
            </Section>
          </>
        )}

        <Section
          title={t('dashboard.sections.apply.title')}
          description={t('dashboard.sections.apply.description')}
        >
          <LicenseCatalogue />
        </Section>
      </Stack>
    </Container>
  );
}

// --------------------------------------------------------------- components

function Hero({
  displayName,
  applicationCount,
  licenseCount,
}: {
  displayName: string;
  applicationCount: number;
  licenseCount: number;
}) {
  const { t } = useTranslation();
  const summary =
    applicationCount === 0 && licenseCount === 0
      ? t('dashboard.hero.summaryEmpty')
      : t('dashboard.hero.summary', {
          applications: t('dashboard.hero.applicationsCount', { count: applicationCount }),
          licences: t('dashboard.hero.licencesCount', { count: licenseCount }),
        });

  return (
    <Paper
      radius="lg"
      p="xl"
      style={{
        background:
          'linear-gradient(135deg, var(--mantine-color-emaPrimary-7) 0%, var(--mantine-color-emaPrimary-9) 55%, var(--mantine-color-emaTeal-8) 100%)',
        color: 'white',
      }}
    >
      <Group justify="space-between" align="flex-start" wrap="nowrap">
        <Box>
          <Text size="sm" style={{ opacity: 0.85 }}>
            {t('app.authority')}
          </Text>
          <Title order={2} mt={4} c="white">
            {displayName ? t('dashboard.welcomeName', { name: displayName }) : t('dashboard.welcome')}
          </Title>
          <Text size="sm" mt="xs" style={{ opacity: 0.9, maxWidth: 560 }}>
            {summary}
          </Text>
        </Box>
        <ThemeIcon
          size={56}
          radius="md"
          variant="transparent"
          c="white"
          visibleFrom="sm"
        >
          <IconShieldCheck size={44} stroke={1.3} />
        </ThemeIcon>
      </Group>
    </Paper>
  );
}

function ActionRequired({
  applications,
  navigate,
}: {
  applications: LicenseApplication[];
  navigate: (path: string) => void;
}) {
  const { t } = useTranslation();
  return (
    <Card
      withBorder
      radius="md"
      padding="md"
      style={{ backgroundColor: 'var(--mantine-color-orange-light)' }}
    >
      <Group gap="xs" mb="sm">
        <ThemeIcon size="sm" radius="xl" color="orange" variant="filled">
          <IconAlertTriangle size={14} />
        </ThemeIcon>
        <Text fw={600} size="sm">
          {t('dashboard.waitingOnYou')}
        </Text>
      </Group>
      <Stack gap="xs">
        {applications.map((app) => {
          const detail = detailFor(app, t);
          return (
            <Paper key={app.id} radius="sm" p="sm" withBorder>
              <Group justify="space-between" wrap="nowrap">
                <Group gap="sm" wrap="nowrap">
                  <ThemeIcon
                    variant="light"
                    color={STATUS_COLORS[app.status]}
                    radius="md"
                  >
                    {app.status === 'PAYMENT_PENDING' ? (
                      <IconCreditCard size={16} />
                    ) : (
                      <IconClipboardList size={16} />
                    )}
                  </ThemeIcon>
                  <Box>
                    <Text size="sm" fw={600}>
                      {app.applicationNumber}
                    </Text>
                    <Text size="xs" c="dimmed">
                      {detail.message}
                    </Text>
                  </Box>
                </Group>
                <Button
                  size="xs"
                  color={detail.color}
                  onClick={() => navigate(detail.path)}
                >
                  {detail.cta}
                </Button>
              </Group>
            </Paper>
          );
        })}
      </Stack>
    </Card>
  );
}

/** What the applicant has to do next, and where that happens. */
function detailFor(
  app: LicenseApplication,
  t: TFunction,
): {
  message: string;
  cta: string;
  color: string;
  path: string;
} {
  const typeKey = app.licenseType?.key;
  const wizard = typeKey
    ? `/licensing/${typeKey}/applications/${app.id}`
    : '/licensing/applications';

  switch (app.status) {
    case 'RESUBMIT_REQUIRED':
      return {
        message: t('dashboard.actionRequired.messages.resubmit'),
        cta: t('dashboard.actionRequired.cta.fixNow'),
        color: 'orange',
        path: wizard,
      };
    case 'PAYMENT_PENDING':
      return {
        message: t('dashboard.actionRequired.messages.paymentPending', {
          amount: formatMoney(app.feeAmount, app.feeCurrency ?? 'ETB', t),
        }),
        cta: t('dashboard.actionRequired.cta.payNow'),
        color: 'yellow',
        path: '/licensing/applications',
      };
    default:
      return {
        message: t('dashboard.actionRequired.messages.draft'),
        cta: t('common.continue'),
        color: 'blue',
        path: wizard,
      };
  }
}

function StatRow({
  inProgress,
  needsMe,
  activeLicenses,
  expiringSoon,
}: {
  inProgress: number;
  needsMe: number;
  activeLicenses: number;
  expiringSoon: number;
}) {
  const { t } = useTranslation();
  const stats = [
    { label: t('applications.stats.inProgress'), value: inProgress, icon: IconClockHour4, color: 'blue' },
    { label: t('dashboard.waitingOnYou'), value: needsMe, icon: IconAlertTriangle, color: 'orange' },
    { label: t('applications.stats.activeLicences'), value: activeLicenses, icon: IconCertificate, color: 'teal' },
    { label: t('dashboard.stats.expiringSoon'), value: expiringSoon, icon: IconClockHour4, color: 'grape' },
  ];

  return (
    <SimpleGrid cols={{ base: 2, md: 4 }} spacing="md">
      {stats.map((stat) => (
        <Card key={stat.label} withBorder radius="md" padding="md">
          <Group justify="space-between" align="flex-start" wrap="nowrap">
            <Box>
              <Text size="xs" c="dimmed" tt="uppercase" fw={600}>
                {stat.label}
              </Text>
              <Text fz={30} fw={700} lh={1.2} mt={4}>
                {stat.value}
              </Text>
            </Box>
            <ThemeIcon variant="light" color={stat.color} radius="md" size="lg">
              <stat.icon size={18} />
            </ThemeIcon>
          </Group>
        </Card>
      ))}
    </SimpleGrid>
  );
}

function Section({
  title,
  description,
  action,
  children,
}: {
  title: string;
  description?: string;
  action?: React.ReactNode;
  children: React.ReactNode;
}) {
  return (
    <Box>
      <Group justify="space-between" align="flex-end" mb="sm">
        <Box>
          <Title order={4}>{title}</Title>
          {description && (
            <Text size="sm" c="dimmed" mt={2}>
              {description}
            </Text>
          )}
        </Box>
        {action}
      </Group>
      {children}
    </Box>
  );
}



function ApplicationTable({
  applications,
  navigate,
  onRefresh,
}: {
  applications: LicenseApplication[];
  navigate: (path: string) => void;
  onRefresh: () => void;
}) {
  const { t } = useTranslation();
  const table = useServerTable();
  const paged = table.paginate(applications);
  return (
    <AdvancedTable
      tableName={t('dashboard.sections.myApplications.title')}
      columns={dashboardApplicationColumns(t)}
      data={paged.rows}
      itemCount={paged.itemCount}
      pageIndex={paged.pageIndex}
      onPageChange={table.setPageIndex}
      pageSize={table.pageSize}
      verticalSpacing="sm"
      refresh={onRefresh}
      onRowClick={(app) =>
        navigate(
          app.licenseType?.key
            ? `/licensing/${app.licenseType.key}/applications/${app.id}`
            : '/licensing/applications',
        )
      }
    />
  );
}

/**
 * The first-visit panel, in place of two empty sections saying the same thing.
 * It carries no call to action of its own — the catalogue is directly beneath
 * it, and a button that only scrolls the page is noise.
 */
function GetStartedPanel() {
  const { t } = useTranslation();
  return (
    <Card withBorder radius="md" padding="xl">
      <Group gap="md" wrap="nowrap" align="flex-start">
        <ThemeIcon variant="light" color="emaPrimary" size={44} radius="md">
          <IconCertificate size={24} stroke={1.5} />
        </ThemeIcon>
        <Box>
          <Title order={4}>{t('dashboard.getStarted.title')}</Title>
          <Text size="sm" c="dimmed" mt={4} maw={620}>
            {t('dashboard.getStarted.body')}
          </Text>
        </Box>
      </Group>
    </Card>
  );
}

function EmptyCard({ message }: { message: string }) {
  return (
    <Card withBorder radius="md" padding="xl">
      <Center>
        <Stack gap={6} align="center">
          <ThemeIcon variant="light" color="gray" size="lg" radius="xl">
            <IconFileText size={18} />
          </ThemeIcon>
          <Text size="sm" c="dimmed" ta="center">
            {message}
          </Text>
        </Stack>
      </Center>
    </Card>
  );
}

export default DashboardPage;
