'use client';
import { Suspense, useState } from 'react';
import { useLocale, useTranslations } from 'next-intl';
import { useSnackbar } from 'notistack';
import {
  Box,
  Chip,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  FormControlLabel,
  MenuItem,
  Skeleton,
  Stack,
  Switch,
  TextField,
} from '@mui/material';
import { AppButton, AppLoading, JalaliDateField } from '@/components';
import { AdminDataTable, AdminEmptyState, AdminErrorState, AdminPageHeader, AdminPager, type AdminTableColumn } from '@/components/admin';
import { formatShamsiDate } from '@/utils';
import { useAdminCapabilities, useAdminListState } from '@/hooks';
import { ADMIN_PAGE_SIZE } from '@/services/admin/constants';
import type { Holiday, HolidayInput, HolidayType } from '@/services/admin/types';
import { useHolidays, useUpsertHoliday } from '@/services/admin';

/** Today's LOCAL date as ISO `YYYY-MM-DD` — never `toISOString()`, which converts to UTC first and can
 * land on the wrong day near local midnight (the same class of bug fixed in the payout window default). */
function todayLocalIso(): string {
  const d = new Date();
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  return `${y}-${m}-${day}`;
}

const HOLIDAY_TYPES: readonly HolidayType[] = ['official', 'religious', 'national'];

/**
 * Iranian-holiday calendar manager (f15). Lists `iranian_holidays`, each with its Shamsi date, name, type,
 * and an `is_bank_closed` flag — the flag that shifts payout scheduling (the copy surfaces that consequence).
 * The client only maintains the calendar the **server** uses for the next-business-day shift; it never
 * computes the shift itself (phase §5).
 */
export default function AdminHolidaysPage() {
  return (
    <Suspense fallback={<AppLoading />}>
      <AdminHolidaysPageInner />
    </Suspense>
  );
}

function AdminHolidaysPageInner() {
  const t = useTranslations('admin');
  const locale = useLocale();
  const caps = useAdminCapabilities();
  const listState = useAdminListState<Record<string, never>>({ parse: () => ({}), serialize: () => ({}), empty: {} });
  const holidays = useHolidays({}, listState.page);
  const [editing, setEditing] = useState<Holiday | 'new' | null>(null);
  const pageCount = Math.max(1, Math.ceil((holidays.data?.total ?? 0) / ADMIN_PAGE_SIZE));

  const columns: AdminTableColumn<Holiday>[] = [
    { key: 'date', header: t('hol_col_date'), render: (h) => formatShamsiDate(h.holidayDate, locale) },
    { key: 'name', header: t('hol_col_name'), render: (h) => h.nameFa },
    { key: 'type', header: t('hol_col_type'), render: (h) => <Chip size="small" variant="outlined" label={t(`htype_${h.type}`)} /> },
    {
      key: 'bank',
      header: t('hol_col_bank'),
      render: (h) => (
        <Chip
          size="small"
          label={h.isBankClosed ? t('yes') : t('no')}
          sx={{
            bgcolor: h.isBankClosed ? 'var(--bal-warning)' : 'var(--bal-divider)',
            color: h.isBankClosed ? 'var(--bal-warning-contrast)' : 'var(--bal-text-secondary)',
            fontWeight: 700,
          }}
        />
      ),
    },
    ...(caps.canConfig
      ? [
          {
            key: 'actions',
            header: '',
            render: (h: Holiday) => (
              <AppButton variant="text" color="primary" startIcon="edit" onClick={() => setEditing(h)}>
                {t('cfg_edit')}
              </AppButton>
            ),
          } as AdminTableColumn<Holiday>,
        ]
      : []),
  ];

  return (
    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
      <AdminPageHeader
        title={t('hol_title')}
        subtitle={t('hol_subtitle')}
        actions={
          caps.canConfig ? (
            <AppButton variant="contained" color="primary" startIcon="add" onClick={() => setEditing('new')}>
              {t('hol_add')}
            </AppButton>
          ) : undefined
        }
      />

      {holidays.isLoading ? (
        <Skeleton variant="rounded" height={200} />
      ) : holidays.isError ? (
        <AdminErrorState message={t('error_generic')} retryLabel={t('retry')} onRetry={() => holidays.refetch()} />
      ) : (holidays.data?.items.length ?? 0) === 0 ? (
        <AdminEmptyState icon="calendar" title={t('hol_empty')} />
      ) : (
        <AdminDataTable columns={columns} rows={holidays.data?.items ?? []} getRowKey={(h) => h.id} ariaLabel={t('hol_title')} />
      )}

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

      {editing ? (
        <HolidayDialog holiday={editing === 'new' ? null : editing} onClose={() => setEditing(null)} />
      ) : null}
    </Box>
  );
}

function HolidayDialog({ holiday, onClose }: { holiday: Holiday | null; onClose: () => void }) {
  const t = useTranslations('admin');
  const { enqueueSnackbar } = useSnackbar();
  const upsert = useUpsertHoliday();
  const [form, setForm] = useState<HolidayInput>(() => ({
    holidayDate: holiday?.holidayDate?.slice(0, 10) ?? todayLocalIso(),
    nameFa: holiday?.nameFa ?? '',
    type: holiday?.type ?? 'official',
    isBankClosed: holiday?.isBankClosed ?? true,
  }));

  const valid = form.holidayDate.length > 0 && form.nameFa.trim().length > 0;

  const onSave = () => {
    if (!valid) return;
    upsert.mutate(
      { ...form, nameFa: form.nameFa.trim() },
      {
        onSuccess: () => {
          enqueueSnackbar(t('hol_saved'), { variant: 'success' });
          onClose();
        },
      },
    );
  };

  return (
    <Dialog open onClose={upsert.isPending ? undefined : onClose} fullWidth maxWidth="xs">
      <DialogTitle sx={{ fontWeight: 800 }}>{holiday ? t('hol_edit') : t('hol_add')}</DialogTitle>
      <DialogContent>
        <Stack sx={{ gap: 2, mt: 1 }}>
          <JalaliDateField
            label={t('hol_col_date')}
            value={form.holidayDate || null}
            onChange={(iso) => setForm((f) => ({ ...f, holidayDate: iso }))}
            disabled={!!holiday}
          />
          <TextField
            label={t('hol_name_fa')}
            value={form.nameFa}
            onChange={(e) => setForm((f) => ({ ...f, nameFa: e.target.value }))}
          />
          <TextField
            select
            label={t('hol_col_type')}
            value={form.type}
            onChange={(e) => setForm((f) => ({ ...f, type: e.target.value as HolidayType }))}
          >
            {HOLIDAY_TYPES.map((ty) => (
              <MenuItem key={ty} value={ty}>
                {t(`htype_${ty}`)}
              </MenuItem>
            ))}
          </TextField>
          <FormControlLabel
            control={<Switch checked={form.isBankClosed} onChange={(e) => setForm((f) => ({ ...f, isBankClosed: e.target.checked }))} />}
            label={t('hol_bank_hint')}
          />
        </Stack>
      </DialogContent>
      <DialogActions sx={{ px: 3, pb: 2 }}>
        <AppButton variant="text" color="inherit" onClick={onClose} disabled={upsert.isPending}>
          {t('cancel')}
        </AppButton>
        <AppButton variant="contained" color="primary" onClick={onSave} disabled={!valid || upsert.isPending}>
          {upsert.isPending ? t('saving') : t('save')}
        </AppButton>
      </DialogActions>
    </Dialog>
  );
}
