'use client';
import { FunctionComponent, ReactNode, useState } from 'react';
import { useParams, useRouter } from 'next/navigation';
import { useLocale, useTranslations } from 'next-intl';
import { useSnackbar } from 'notistack';
import { Box, Chip, Paper, Skeleton, Stack, TextField, Typography } from '@mui/material';
import { AppButton, StatusChip } from '@/components';
import type { StatusKind } from '@/components';
import { AdminEmptyState, AdminErrorState, AdminPager, ConfirmDialog } from '@/components/admin';
import { useAdminCapabilities } from '@/hooks';
import { ROUTES } from '@/constants';
import { formatIrrToToman, formatShamsiDate } from '@/utils';
import { usePayoutBatchDetail, useRecordTransferReference, useRetryPayout } from '@/services/payouts';
import type { AdminPayoutRow, PayoutBatchStatus, PayoutStatus } from '@/services/payouts/types';

const BATCH_STATUS_KIND: Record<PayoutBatchStatus, StatusKind> = {
  draft: 'neutral',
  processing: 'info',
  partially_failed: 'pending',
  completed: 'verified',
  failed: 'rejected',
};

const PAYOUT_STATUS_KIND: Record<PayoutStatus, StatusKind> = {
  pending: 'pending',
  submitted: 'info',
  paid: 'verified',
  failed: 'rejected',
};

/**
 * Admin payout-batch detail (f15) — one batch expanded: its window + holiday-shifted processing date, and its
 * paginated per-payout rows (money decomposition, masked IBAN, transfer reference, status). A failed payout
 * can be retried (idempotency-keyed) and a reconciled bank transfer reference recorded — both gated on
 * `canPayout`. Money is display-only Toman; the client never recomputes amounts, eligibility, or dates.
 */
export default function AdminPayoutBatchDetailPage() {
  const t = useTranslations('admin');
  const locale = useLocale();
  const router = useRouter();
  const caps = useAdminCapabilities();
  const params = useParams<{ batchId: string }>();
  const batchId = Number(params?.batchId);

  const [page, setPage] = useState(1);
  const detail = usePayoutBatchDetail(Number.isFinite(batchId) ? batchId : null, page);
  const data = detail.data;
  const pageCount = data ? Math.max(1, Math.ceil(data.total / data.pageSize)) : 1;

  return (
    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
      <Stack sx={{ gap: 0.5 }}>
        <AppButton
          variant="text"
          color="primary"
          onClick={() => router.push(`/${locale}${ROUTES.ADMIN_PAYOUTS}`)}
          sx={{ alignSelf: 'flex-start' }}
        >
          {t('back')}
        </AppButton>
        <Typography variant="h5" component="h1" sx={{ fontWeight: 800 }}>
          {t('payout_batch_title', { id: batchId })}
        </Typography>
      </Stack>

      {detail.isLoading ? (
        <Stack sx={{ gap: 2 }}>
          <Skeleton variant="rounded" height={120} />
          <Skeleton variant="rounded" height={96} />
          <Skeleton variant="rounded" height={96} />
        </Stack>
      ) : detail.isError ? (
        <AdminErrorState message={t('error_generic')} retryLabel={t('retry')} onRetry={() => detail.refetch()} />
      ) : !data ? (
        <AdminEmptyState icon="wallet" title={t('payout_empty')} />
      ) : (
        <>
          <Paper elevation={0} sx={{ p: 2.5, border: '1px solid', borderColor: 'divider', borderRadius: 2 }}>
            <Stack sx={{ gap: 1.5 }}>
              <StatusChip
                status={BATCH_STATUS_KIND[data.batch.status]}
                label={t(`batch_status_${data.batch.status}`)}
                sx={{ alignSelf: 'flex-start' }}
              />
              <MetaLine label={t('payout_col_period')}>
                {formatShamsiDate(data.batch.periodStart, locale)} – {formatShamsiDate(data.batch.periodEnd, locale)}
              </MetaLine>
              <MetaLine label={t('payout_col_processing')}>
                <Stack direction="row" sx={{ gap: 0.75, alignItems: 'center', flexWrap: 'wrap' }}>
                  <span>{formatShamsiDate(data.batch.processingDate, locale)}</span>
                  {data.batch.holidayShifted ? (
                    <Chip
                      size="small"
                      label={t('payout_holiday_shift')}
                      sx={{ bgcolor: 'var(--bal-warning)', color: 'var(--bal-warning-contrast)', fontWeight: 500 }}
                    />
                  ) : null}
                </Stack>
              </MetaLine>
            </Stack>
          </Paper>

          <Stack sx={{ gap: 1.5 }}>
            <Typography variant="subtitle1" sx={{ fontWeight: 700 }}>
              {t('payout_rows_title')}
            </Typography>
            {data.payouts.length === 0 ? (
              <AdminEmptyState icon="wallet" title={t('payout_empty')} />
            ) : (
              data.payouts.map((row) => (
                <PayoutRowCard key={row.id} row={row} batchId={batchId} canPayout={caps.canPayout} />
              ))
            )}
          </Stack>

          <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 })}
          />
        </>
      )}
    </Box>
  );
}

/**
 * One `nurse_payouts` row — the money decomposition (`gross − clawback = net`), masked IBAN + transfer
 * reference, status, and (for a failed payout) the reason + an idempotency-keyed retry. Recording a
 * reconciled bank transfer reference is an inline per-row action. Both writes are gated on `canPayout`.
 */
const PayoutRowCard: FunctionComponent<{ row: AdminPayoutRow; batchId: number; canPayout: boolean }> = ({
  row,
  batchId,
  canPayout,
}) => {
  const t = useTranslations('admin');
  const locale = useLocale();
  const { enqueueSnackbar } = useSnackbar();

  const retry = useRetryPayout();
  const record = useRecordTransferReference();
  const [retryOpen, setRetryOpen] = useState(false);
  const [reference, setReference] = useState('');

  const onRetryConfirm = () => {
    retry.mutate(
      { payoutId: row.id, idempotencyKey: crypto?.randomUUID?.() ?? String(Date.now()), batchId },
      {
        onSuccess: () => {
          setRetryOpen(false);
          enqueueSnackbar(t('saved'), { variant: 'success' });
        },
      },
    );
  };

  const onRecord = () => {
    record.mutate(
      { payoutId: row.id, reference: reference.trim(), batchId },
      {
        onSuccess: () => {
          enqueueSnackbar(t('payout_ref_saved'), { variant: 'success' });
          setReference('');
        },
      },
    );
  };

  return (
    <Paper elevation={0} sx={{ p: 2, border: '1px solid', borderColor: 'divider', borderRadius: 2 }}>
      <Stack sx={{ gap: 1.25 }}>
        <Stack
          direction="row"
          sx={{ justifyContent: 'space-between', gap: 1, alignItems: 'center', flexWrap: 'wrap' }}
        >
          <Typography variant="subtitle2" sx={{ fontWeight: 800 }}>
            {t('payout_row_nurse')}: {row.nurseName ?? `#${row.nurseId}`}
          </Typography>
          <StatusChip status={PAYOUT_STATUS_KIND[row.status]} label={t(`pstatus_${row.status}`)} />
        </Stack>

        <Typography variant="body2" sx={{ color: 'text.secondary' }}>
          {t('payout_decomp', {
            gross: formatIrrToToman(row.grossEarningsIrr, locale),
            clawback: formatIrrToToman(row.clawbackAppliedIrr, locale),
            net: formatIrrToToman(row.netAmountIrr, locale),
          })}
        </Typography>

        <Stack direction="row" sx={{ gap: 3, flexWrap: 'wrap' }}>
          <Field label={t('masked_iban_label')}>
            <Box component="span" dir="ltr">
              {row.maskedIban}
            </Box>
          </Field>
          <Field label={t('payout_row_ref')}>
            <Box component="span" dir="ltr">
              {row.transferReference ?? '—'}
            </Box>
          </Field>
        </Stack>

        {row.status === 'failed' ? (
          <Box
            sx={{
              p: 1.25,
              borderRadius: 2,
              border: '1px solid',
              borderColor: 'divider',
              borderInlineStart: '3px solid',
              borderInlineStartColor: 'var(--bal-error)',
            }}
          >
            <Typography variant="caption" sx={{ color: 'text.secondary' }} dir="ltr">
              {t('payout_failure_reason', { reason: row.failureReason ?? '—' })}
            </Typography>
            {canPayout ? (
              <Box sx={{ mt: 1 }}>
                <AppButton
                  variant="outlined"
                  color="error"
                  onClick={() => setRetryOpen(true)}
                  disabled={retry.isPending}
                >
                  {t('payout_retry')}
                </AppButton>
              </Box>
            ) : null}
          </Box>
        ) : null}

        {canPayout ? (
          <Stack direction="row" sx={{ gap: 1, alignItems: 'center', flexWrap: 'wrap', mt: 0.5 }}>
            <TextField
              size="small"
              label={t('payout_record_ref')}
              placeholder={t('payout_record_ref_ph')}
              value={reference}
              onChange={(e) => setReference(e.target.value)}
              slotProps={{ htmlInput: { dir: 'ltr' } }}
              sx={{ minWidth: 220 }}
            />
            <AppButton
              variant="contained"
              color="primary"
              onClick={onRecord}
              disabled={reference.trim().length === 0 || record.isPending}
            >
              {record.isPending ? t('saving') : t('save')}
            </AppButton>
          </Stack>
        ) : null}
      </Stack>

      <ConfirmDialog
        open={retryOpen}
        title={t('payout_retry')}
        body={t('payout_retry_confirm')}
        confirmLabel={t('confirm')}
        cancelLabel={t('cancel')}
        onConfirm={onRetryConfirm}
        onClose={() => setRetryOpen(false)}
        loading={retry.isPending}
        confirmColor="error"
      />
    </Paper>
  );
};

const MetaLine: FunctionComponent<{ label: string; children: ReactNode }> = ({ label, children }) => (
  <Stack direction="row" sx={{ gap: 1, justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap' }}>
    <Typography variant="body2" sx={{ color: 'text.secondary' }}>
      {label}
    </Typography>
    <Box sx={{ fontWeight: 500, typography: 'body2' }}>{children}</Box>
  </Stack>
);

const Field: FunctionComponent<{ label: string; children: ReactNode }> = ({ label, children }) => (
  <Stack sx={{ gap: 0.25 }}>
    <Typography variant="caption" sx={{ color: 'text.secondary' }}>
      {label}
    </Typography>
    <Typography variant="body2" sx={{ fontWeight: 500 }}>
      {children}
    </Typography>
  </Stack>
);
