'use client';
import { Suspense, useState } from 'react';
import { useLocale, useTranslations } from 'next-intl';
import { FormProvider, useForm } from 'react-hook-form';
import { useSnackbar } from 'notistack';
import {
  Box,
  Chip,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  FormControlLabel,
  MenuItem,
  Skeleton,
  Stack,
  Switch,
} from '@mui/material';
import { AppButton, AppLoading, RhfControlGroup, RhfJalaliDateField, RhfTextField } 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 = useForm<HolidayInput>({
    mode: 'onTouched',
    defaultValues: {
      holidayDate: holiday?.holidayDate?.slice(0, 10) ?? todayLocalIso(),
      nameFa: holiday?.nameFa ?? '',
      type: holiday?.type ?? 'official',
      isBankClosed: holiday?.isBankClosed ?? true,
    },
  });
  const { handleSubmit, formState } = form;

  const onSave = (values: HolidayInput) =>
    upsert.mutate(
      { ...values, nameFa: values.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>
      <FormProvider {...form}>
        <DialogContent>
          {/* A real <form> so Enter submits from any field; the footer button (outside DialogContent)
              calls the same handler directly rather than relying on cross-element form association. */}
          <Stack component="form" noValidate onSubmit={handleSubmit(onSave)} sx={{ gap: 2, mt: 1 }}>
            <RhfJalaliDateField<HolidayInput>
              name="holidayDate"
              label={t('hol_col_date')}
              rules={{ validate: (value) => String(value ?? '').length > 0 }}
              disabled={!!holiday}
            />
            <RhfTextField<HolidayInput>
              name="nameFa"
              label={t('hol_name_fa')}
              rules={{ validate: (value) => String(value ?? '').trim().length > 0 }}
            />
            <RhfTextField<HolidayInput> name="type" select label={t('hol_col_type')}>
              {HOLIDAY_TYPES.map((ty) => (
                <MenuItem key={ty} value={ty}>
                  {t(`htype_${ty}`)}
                </MenuItem>
              ))}
            </RhfTextField>
            <RhfControlGroup<HolidayInput> name="isBankClosed">
              {({ field }) => (
                <FormControlLabel
                  control={
                    <Switch checked={Boolean(field.value)} onChange={(event) => field.onChange(event.target.checked)} />
                  }
                  label={t('hol_bank_hint')}
                />
              )}
            </RhfControlGroup>
          </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={handleSubmit(onSave)}
            disabled={!formState.isValid || upsert.isPending}
          >
            {upsert.isPending ? t('saving') : t('save')}
          </AppButton>
        </DialogActions>
      </FormProvider>
    </Dialog>
  );
}
