'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import { useLocale, useTranslations } from 'next-intl';
import { useSnackbar } from 'notistack';
import {
  Box,
  Chip,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  Divider,
  MenuItem,
  Skeleton,
  Stack,
  TextField,
  Typography,
} from '@mui/material';
import { AppButton, Money, StatusChip } from '@/components';
import type { StatusKind } from '@/components';
import {
  AdminDataTable,
  AdminEmptyState,
  AdminErrorState,
  AdminPageHeader,
  AdminPager,
  ConfirmDialog,
} from '@/components/admin';
import type { AdminTableColumn } from '@/components/admin';
import { useAdminCapabilities } from '@/hooks';
import { adminPayoutBatchPath } from '@/constants';
import { formatShamsiDate } from '@/utils';
import { PAYOUTS_PAGE_SIZE } from '@/services/payouts/constants';
import { usePayoutBatches, usePreviewPayoutBatch, useRunPayoutBatch } from '@/services/payouts';
import type { PayoutBatchStatus, PayoutBatchSummary } from '@/services/payouts/types';

/** Batch lifecycle → semantic chip color (server truth; the client only renders it). */
const BATCH_STATUS_KIND: Record<PayoutBatchStatus, StatusKind> = {
  draft: 'neutral',
  processing: 'info',
  partially_failed: 'pending',
  completed: 'verified',
  failed: 'rejected',
};

const BATCH_STATUSES: readonly PayoutBatchStatus[] = [
  'draft',
  'processing',
  'partially_failed',
  'completed',
  'failed',
];

/** UTC ISO date (`YYYY-MM-DD`) — the wire shape for the batch window. */
const isoDate = (d: Date): string => d.toISOString().slice(0, 10);

/**
 * Admin payout-batch dashboard (f15) — the reconciliation list of weekly `nurse_payout_batches` and the
 * entry point to previewing + running the next batch. Money is IRR digit-strings rendered as display-only
 * Toman; the server owns eligibility and the holiday-shifted processing date — the client never computes
 * them. Running a batch moves money, so it is gated (`canPayout`), idempotency-keyed, and confirmed.
 */
export default function AdminPayoutsPage() {
  const t = useTranslations('admin');
  const locale = useLocale();
  const router = useRouter();
  const caps = useAdminCapabilities();

  const [status, setStatus] = useState<PayoutBatchStatus | ''>('');
  const [page, setPage] = useState(1);
  const [previewOpen, setPreviewOpen] = useState(false);

  const filters = { status: status || undefined };
  const batches = usePayoutBatches(filters, page);

  const items = batches.data?.items ?? [];
  const pageCount = Math.max(1, Math.ceil((batches.data?.total ?? 0) / PAYOUTS_PAGE_SIZE));

  const columns: AdminTableColumn<PayoutBatchSummary>[] = [
    {
      key: 'period',
      header: t('payout_col_period'),
      render: (b) => `${formatShamsiDate(b.periodStart, locale)} – ${formatShamsiDate(b.periodEnd, locale)}`,
    },
    {
      key: 'count',
      header: t('payout_col_count'),
      render: (b) => b.payoutCount,
    },
    {
      key: 'total',
      header: t('payout_col_total'),
      render: (b) => <Money amountIrr={b.totalAmount} size="sm" />,
    },
    {
      key: 'status',
      header: t('payout_col_status'),
      render: (b) => <StatusChip status={BATCH_STATUS_KIND[b.status]} label={t(`batch_status_${b.status}`)} />,
    },
    {
      key: 'processing',
      header: t('payout_col_processing'),
      render: (b) => (
        <Stack direction="row" sx={{ gap: 0.75, alignItems: 'center', flexWrap: 'wrap' }}>
          <span>{formatShamsiDate(b.processingDate, locale)}</span>
          {b.holidayShifted ? (
            <Chip
              size="small"
              label={t('payout_holiday_shift')}
              sx={{ bgcolor: 'var(--bal-warning)', color: 'var(--bal-warning-contrast)', fontWeight: 500 }}
            />
          ) : null}
        </Stack>
      ),
    },
  ];

  return (
    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
      <AdminPageHeader
        title={t('payout_title')}
        subtitle={t('payout_subtitle')}
        actions={
          <Stack direction="row" sx={{ gap: 1, flexWrap: 'wrap', alignItems: 'center' }}>
            <TextField
              select
              size="small"
              label={t('payout_col_status')}
              value={status}
              onChange={(e) => {
                setStatus(e.target.value as PayoutBatchStatus | '');
                setPage(1);
              }}
              sx={{ minWidth: 160 }}
            >
              <MenuItem value="">{t('filter_all')}</MenuItem>
              {BATCH_STATUSES.map((s) => (
                <MenuItem key={s} value={s}>
                  {t(`batch_status_${s}`)}
                </MenuItem>
              ))}
            </TextField>
            {caps.canPayout ? (
              <AppButton variant="contained" color="primary" onClick={() => setPreviewOpen(true)}>
                {t('payout_preview')}
              </AppButton>
            ) : null}
          </Stack>
        }
      />

      {batches.isLoading ? (
        <Stack sx={{ gap: 2 }}>{[0, 1, 2].map((k) => <Skeleton key={k} variant="rounded" height={64} />)}</Stack>
      ) : batches.isError ? (
        <AdminErrorState message={t('error_generic')} retryLabel={t('retry')} onRetry={() => batches.refetch()} />
      ) : items.length === 0 ? (
        <AdminEmptyState icon="wallet" title={t('payout_empty')} />
      ) : (
        <AdminDataTable
          columns={columns}
          rows={items}
          getRowKey={(b) => b.id}
          onRowClick={(b) => router.push(`/${locale}${adminPayoutBatchPath(b.id)}`)}
          ariaLabel={t('payout_title')}
        />
      )}

      <AdminPager
        page={page}
        pageCount={pageCount}
        onPrev={() => setPage((p) => Math.max(1, p - 1))}
        onNext={() => setPage((p) => Math.min(pageCount, p + 1))}
        prevLabel={t('prev_page')}
        nextLabel={t('next_page')}
        indicator={t('page_indicator', { page })}
      />

      {previewOpen ? <PreviewBatchDialog canPayout={caps.canPayout} onClose={() => setPreviewOpen(false)} /> : null}
    </Box>
  );
}

/**
 * The eligibility dry-run + run-batch dialog. Preview is a mutation (runs only when the admin asks), and its
 * eligible/skipped breakdown + the server's holiday-shifted processing date are read straight from the
 * mutation's `data`. Running is idempotency-keyed and confirmed; on success it deep-links to the new batch.
 */
function PreviewBatchDialog({ canPayout, onClose }: { canPayout: boolean; onClose: () => void }) {
  const t = useTranslations('admin');
  const locale = useLocale();
  const router = useRouter();
  const { enqueueSnackbar } = useSnackbar();

  // Default the window to the last 7 days (end = today). A lazy initializer runs the `Date` read once.
  const [periodStart, setPeriodStart] = useState(() =>
    isoDate(new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)),
  );
  const [periodEnd, setPeriodEnd] = useState(() => isoDate(new Date()));
  const [runConfirmOpen, setRunConfirmOpen] = useState(false);

  const preview = usePreviewPayoutBatch();
  const run = useRunPayoutBatch();
  const result = preview.data;

  const onPreview = () => {
    if (!periodStart || !periodEnd) return;
    preview.mutate({ periodStart, periodEnd });
  };

  const onRunConfirm = () => {
    const idempotencyKey = crypto?.randomUUID
      ? crypto.randomUUID()
      : `batch_${periodStart}_${periodEnd}_${Date.now()}`;
    run.mutate(
      { periodStart, periodEnd, idempotencyKey },
      {
        onSuccess: (batch) => {
          setRunConfirmOpen(false);
          onClose();
          enqueueSnackbar(t('payout_ran'), { variant: 'success' });
          router.push(`/${locale}${adminPayoutBatchPath(batch.id)}`);
        },
      },
    );
  };

  return (
    <Dialog open onClose={run.isPending ? undefined : onClose} fullWidth maxWidth="sm">
      <DialogTitle sx={{ fontWeight: 800 }}>{t('payout_preview_title')}</DialogTitle>
      <DialogContent>
        <Stack direction="row" sx={{ gap: 1.5, mt: 1, flexWrap: 'wrap', alignItems: 'center' }}>
          <TextField
            type="date"
            size="small"
            label={t('payout_period_start')}
            value={periodStart}
            onChange={(e) => setPeriodStart(e.target.value)}
            slotProps={{ inputLabel: { shrink: true } }}
          />
          <TextField
            type="date"
            size="small"
            label={t('payout_period_end')}
            value={periodEnd}
            onChange={(e) => setPeriodEnd(e.target.value)}
            slotProps={{ inputLabel: { shrink: true } }}
          />
          <AppButton
            variant="outlined"
            color="primary"
            onClick={onPreview}
            disabled={!periodStart || !periodEnd || preview.isPending}
          >
            {t('payout_preview')}
          </AppButton>
        </Stack>

        {result ? (
          <Stack sx={{ gap: 2, mt: 2.5 }}>
            <Stack direction="row" sx={{ gap: 1, alignItems: 'center', flexWrap: 'wrap' }}>
              <Typography variant="body2" sx={{ color: 'text.secondary' }}>
                {t('payout_col_processing')}
              </Typography>
              <Typography variant="body2" sx={{ fontWeight: 700 }}>
                {formatShamsiDate(result.processingDate, locale)}
              </Typography>
              {result.holidayShifted ? (
                <Chip
                  size="small"
                  label={t('payout_holiday_shift')}
                  sx={{ bgcolor: 'var(--bal-warning)', color: 'var(--bal-warning-contrast)', fontWeight: 500 }}
                />
              ) : null}
            </Stack>

            <Stack sx={{ gap: 1 }}>
              <Typography variant="subtitle2" sx={{ fontWeight: 800 }}>
                {t('payout_eligible_nurses')}
              </Typography>
              {result.eligible.length === 0 ? (
                <Typography variant="body2" sx={{ color: 'text.secondary' }}>
                  —
                </Typography>
              ) : (
                <Stack divider={<Divider />} sx={{ border: '1px solid', borderColor: 'divider', borderRadius: 2 }}>
                  {result.eligible.map((n) => (
                    <Stack key={n.nurseId} sx={{ p: 1.5, gap: 0.5 }}>
                      <Stack
                        direction="row"
                        sx={{ justifyContent: 'space-between', gap: 1, alignItems: 'center', flexWrap: 'wrap' }}
                      >
                        <Typography variant="body2" sx={{ fontWeight: 700 }}>
                          {n.nurseName ?? `#${n.nurseId}`}
                        </Typography>
                        {!n.hasVerifiedPrimaryIban ? (
                          <Chip
                            size="small"
                            label={t('payout_no_iban')}
                            sx={{ bgcolor: 'var(--bal-error)', color: 'var(--bal-error-contrast)', fontWeight: 500 }}
                          />
                        ) : null}
                      </Stack>
                      <Typography variant="caption" sx={{ color: 'text.secondary' }}>
                        {t('payout_col_gross')}: <Money amountIrr={n.grossEarningsIrr} size="sm" hideUnit /> ·{' '}
                        {t('payout_col_clawback')}: <Money amountIrr={n.clawbackAppliedIrr} size="sm" hideUnit /> ·{' '}
                        {t('payout_col_net')}: <Money amountIrr={n.netAmountIrr} size="sm" />
                      </Typography>
                    </Stack>
                  ))}
                </Stack>
              )}
            </Stack>

            {result.skipped.length > 0 ? (
              <Stack sx={{ gap: 1 }}>
                <Typography variant="subtitle2" sx={{ fontWeight: 800 }}>
                  {t('payout_skipped')}
                </Typography>
                <Stack divider={<Divider />} sx={{ border: '1px solid', borderColor: 'divider', borderRadius: 2 }}>
                  {result.skipped.map((n) => (
                    <Stack
                      key={n.nurseId}
                      direction="row"
                      sx={{ p: 1.5, justifyContent: 'space-between', gap: 1, flexWrap: 'wrap' }}
                    >
                      <Typography variant="body2" sx={{ fontWeight: 700 }}>
                        {n.nurseName ?? `#${n.nurseId}`}
                      </Typography>
                      <Typography variant="caption" sx={{ color: 'text.secondary' }} dir="ltr">
                        {n.reason}
                      </Typography>
                    </Stack>
                  ))}
                </Stack>
              </Stack>
            ) : null}

            <Typography variant="caption" sx={{ color: 'text.secondary' }}>
              {t('payout_eligibility_note')}
            </Typography>
          </Stack>
        ) : null}
      </DialogContent>
      <DialogActions sx={{ px: 3, pb: 2 }}>
        <AppButton variant="text" color="inherit" onClick={onClose} disabled={run.isPending}>
          {t('cancel')}
        </AppButton>
        {canPayout ? (
          <AppButton
            variant="contained"
            color="primary"
            onClick={() => setRunConfirmOpen(true)}
            disabled={!result || run.isPending}
          >
            {t('payout_run')}
          </AppButton>
        ) : null}
      </DialogActions>

      <ConfirmDialog
        open={runConfirmOpen}
        title={t('payout_run_confirm_title')}
        body={t('payout_run_confirm_body')}
        confirmLabel={t('payout_run')}
        cancelLabel={t('cancel')}
        onConfirm={onRunConfirm}
        onClose={() => setRunConfirmOpen(false)}
        loading={run.isPending}
      />
    </Dialog>
  );
}
