'use client';
import { FunctionComponent, useMemo, useState } from 'react';
import { useLocale, useTranslations } from 'next-intl';
import { useRouter } from 'next/navigation';
import { FormProvider, useForm, useWatch } from 'react-hook-form';
import { useSnackbar } from 'notistack';
import { Box, Chip, Paper, Stack, TextField, Typography } from '@mui/material';
import {
  AppButton,
  AppIcon,
  AppLoading,
  DocumentUpload,
  FormSection,
  RhfChipSelect,
  RhfJalaliDateField,
  RhfTextField,
} from '@/components';
import type { UploadedDocInfo } from '@/components';
import { CONTENT_MAX_WIDTH } from '@/components/config';
import { ROUTES } from '@/constants';
import { formatShamsiDate } from '@/utils';
import {
  useSubmitCredentials,
  useUploadVerificationDocument,
  useVerificationStatus,
} from '@/services/verification';
import { SPECIALTY_PRESETS } from '@/services/verification/types';
import type { VerificationStatus, VerificationStep } from '@/services/verification/types';
import { stepDescriptionKey, stepLabelKey } from '../verificationSteps';
import VerificationJourneyHeader from '../VerificationJourneyHeader';

const MANUAL_CREDENTIAL_CODES = ['moh_competency_license', 'ino_membership', 'criminal_record'];

interface CredentialsFormValues {
  inoNumber: string;
  specialties: string[];
  issuingAuthority: string;
  issuedAt: string | null;
  expiresAt: string | null;
}

/**
 * B5 — professional credentials. Renders a `DocumentUpload` for **each manual credential step in the
 * status** (data-driven — a new manual step renders without a code change); each upload moves its step
 * to `in_review` (manual admin review — copy never claims an automated authority check).
 *
 * The whole screen used to be one undivided column: a number field, three uploaders, a chip row with
 * its own add-a-custom-value sub-form, two date pickers and a submit button, with two independent
 * `editingIno ? … : …` branches interleaved through it. Grouping the same content into four named
 * sections — شماره نظام / مدارک / تخصص‌ها / جزئیات مدرک — makes the two genuinely optional groups
 * visibly optional and gives the "what still blocks submit?" answer somewhere to live.
 */
export default function CredentialsSubmitPage() {
  const t = useTranslations('verification');
  const locale = useLocale();

  const { data: status, isLoading } = useVerificationStatus();

  const manualSteps = useMemo(
    () => (status?.steps ?? []).filter((step) => MANUAL_CREDENTIAL_CODES.includes(step.code)),
    [status],
  );

  if (isLoading) return <AppLoading />;

  if (!status || manualSteps.length === 0) {
    return (
      <Box sx={{ display: 'flex', flexDirection: 'column', gap: 2, maxWidth: CONTENT_MAX_WIDTH, mx: 'auto', width: '100%' }}>
        <VerificationJourneyHeader group="credentials" />
        <Typography variant="body2" sx={{ color: 'text.secondary' }}>
          {t('credentials_needs_start')}
        </Typography>
        <AppButton color="primary" variant="contained" to={`/${locale}${ROUTES.NURSE_VERIFICATION}`} sx={{ alignSelf: 'flex-start' }}>
          {t('back_to_checklist')}
        </AppButton>
      </Box>
    );
  }

  return <CredentialsForm status={status} manualSteps={manualSteps} />;
}

/**
 * Hydrates from `status.credentialSubmission` (REQ-056, mock-tolerant) as react-hook-form
 * `defaultValues` — mounted only once the status query has resolved, which is what lets the server
 * read-back *be* the initial form state instead of being copied into it by a render-time state
 * adjustment. Once the INO number has been recorded the field locks into a "شمارهٔ نظام ثبت شد"
 * summary — never re-prompted as if lost, and never re-sent blank (the server's
 * `CredentialDetailsInput.inoNumber` is required; the raw number is never read back by design, so
 * re-submitting it isn't possible without the nurse re-entering it via "تغییر"). A returning,
 * already-submitted nurse can still fix a **rejected** document directly (each upload takes effect
 * immediately, no re-submit needed) and simply returns to the journey.
 */
const CredentialsForm: FunctionComponent<{ status: VerificationStatus; manualSteps: VerificationStep[] }> = ({
  status,
  manualSteps,
}) => {
  const t = useTranslations('verification');
  const tc = useTranslations('common');
  const locale = useLocale();
  const router = useRouter();
  const { enqueueSnackbar } = useSnackbar();

  const uploadDocument = useUploadVerificationDocument();
  const submitCredentials = useSubmitCredentials();
  const submission = status.credentialSubmission;

  const [editingIno, setEditingIno] = useState(!submission?.inoNumberSubmitted);
  const [customSpecialty, setCustomSpecialty] = useState('');
  const [uploadedSteps, setUploadedSteps] = useState<Record<number, boolean>>({});

  const form = useForm<CredentialsFormValues>({
    mode: 'onTouched',
    defaultValues: {
      inoNumber: '',
      specialties: submission?.specialties ?? [],
      issuingAuthority: submission?.issuingAuthority ?? '',
      issuedAt: submission?.issuedAt ?? null,
      expiresAt: submission?.expiresAt ?? null,
    },
  });
  const { control, handleSubmit, setValue } = form;
  const specialties = useWatch({ control, name: 'specialties' });
  const issuedAt = useWatch({ control, name: 'issuedAt' });
  const expiresAt = useWatch({ control, name: 'expiresAt' });
  const issuingAuthority = useWatch({ control, name: 'issuingAuthority' });

  const addCustomSpecialty = () => {
    const value = customSpecialty.trim();
    if (value && !specialties.includes(value)) {
      setValue('specialties', [...specialties, value], { shouldDirty: true });
    }
    setCustomSpecialty('');
  };

  const uploadToStep = (step: VerificationStep) => async (file: File, onProgress: (percent: number) => void) => {
    const doc = await uploadDocument.mutateAsync({ stepId: step.id, file, onProgress });
    return { name: doc.originalFileName ?? file.name, sizeBytes: doc.fileSizeBytes } satisfies UploadedDocInfo;
  };

  // A returning nurse with any manual step already on file (server truth) is never dead-ended: while
  // actively (re-)entering the INO number, the gate also counts server-side documents, not only this
  // session's uploads.
  const uploadedCount =
    manualSteps.filter((step) => uploadedSteps[step.id] || step.status === 'in_review' || step.status === 'passed')
      .length;
  const hasAnyDocument = uploadedCount > 0;

  const submit = (values: CredentialsFormValues) => {
    submitCredentials.mutate(
      {
        inoNumber: values.inoNumber.trim(),
        specialties: values.specialties,
        issuingAuthority: values.issuingAuthority.trim() || undefined,
        issuedAt: values.issuedAt ?? undefined,
        expiresAt: values.expiresAt ?? undefined,
      },
      {
        onSuccess: () => {
          enqueueSnackbar(t('credentials_submitted'), { variant: 'success' });
          router.push(`/${locale}${ROUTES.NURSE_VERIFICATION_REVIEW}`);
        },
        onError: () => enqueueSnackbar(t('credentials_error'), { variant: 'error' }),
      },
    );
  };

  return (
    <FormProvider {...form}>
      <Box
        component="form"
        noValidate
        onSubmit={handleSubmit(submit)}
        sx={{ display: 'flex', flexDirection: 'column', gap: 2.5, maxWidth: CONTENT_MAX_WIDTH, mx: 'auto', width: '100%' }}
      >
        <VerificationJourneyHeader group="credentials" />

        <Typography variant="body2" sx={{ color: 'text.secondary' }}>
          {t('credentials_subtitle')}
        </Typography>

        <FormSection title={t('ino_number_label')} description={t('ino_number_hint')} icon="license">
          {editingIno ? (
            <RhfTextField<CredentialsFormValues>
              name="inoNumber"
              label={t('ino_number_label')}
              rules={{ required: t('ino_number_required') }}
              slotProps={{ htmlInput: { dir: 'ltr', style: { textAlign: 'start' } } }}
              fullWidth
            />
          ) : (
            <Stack
              direction="row"
              sx={{ gap: 1, alignItems: 'center', justifyContent: 'space-between', p: 1.5, borderRadius: 'var(--bal-radius-md)', border: '1px solid', borderColor: 'divider' }}
            >
              <Stack direction="row" sx={{ gap: 1, alignItems: 'center' }}>
                <AppIcon icon="verified" size={18} color="var(--bal-success)" />
                <Typography variant="body2">{t('ino_number_submitted')}</Typography>
              </Stack>
              <AppButton variant="text" color="primary" onClick={() => setEditingIno(true)}>
                {t('ino_number_change')}
              </AppButton>
            </Stack>
          )}
        </FormSection>

        {/* One uploader per manual credential step — data-driven from the status. Re-uploading a
            rejected document always takes effect immediately, whether or not the INO number is locked. */}
        <FormSection
          title={t('credentials_documents_title')}
          description={t('credentials_documents_description')}
          icon="document"
          status={
            <Typography variant="caption" sx={{ color: 'text.secondary', flexShrink: 0 }}>
              {t('credentials_documents_count', { done: uploadedCount, total: manualSteps.length })}
            </Typography>
          }
        >
          {manualSteps.map((step) => (
            <DocumentUpload
              key={step.code}
              label={t.has(stepLabelKey(step.code)) ? t(stepLabelKey(step.code)) : step.displayName}
              hint={t.has(stepDescriptionKey(step.code)) ? t(stepDescriptionKey(step.code)) : undefined}
              onUpload={uploadToStep(step)}
              onUploaded={() => setUploadedSteps((prev) => ({ ...prev, [step.id]: true }))}
              rejected={step.status === 'failed'}
              rejectionReason={step.failureReason ?? undefined}
              existingDoc={step.status === 'in_review' || step.status === 'passed' ? { name: t('doc_uploaded') } : null}
            />
          ))}

          {editingIno ? (
            <DocumentUpload label={t('education_label')} hint={t('education_hint')} onUpload={async (file) => ({ name: file.name })} />
          ) : null}
        </FormSection>

        <FormSection
          title={t('specialties_label')}
          description={t('specialties_hint')}
          icon="clinical"
          optional
          optionalLabel={tc('optional')}
        >
          {editingIno ? (
            <>
              <RhfChipSelect<CredentialsFormValues>
                name="specialties"
                options={SPECIALTY_PRESETS.map((preset) => ({
                  code: preset,
                  label: t.has(`specialty_${preset}`) ? t(`specialty_${preset}`) : preset,
                }))}
                allowCustomValues
              />
              <Stack direction="row" sx={{ gap: 1, alignItems: 'flex-start' }}>
                <TextField
                  size="small"
                  placeholder={t('specialty_add_placeholder')}
                  value={customSpecialty}
                  onChange={(event) => setCustomSpecialty(event.target.value)}
                  onKeyDown={(event) => {
                    if (event.key === 'Enter') {
                      event.preventDefault();
                      addCustomSpecialty();
                    }
                  }}
                />
                <AppButton variant="outlined" color="primary" startIcon="add" onClick={addCustomSpecialty}>
                  {t('specialty_add')}
                </AppButton>
              </Stack>
            </>
          ) : specialties.length > 0 ? (
            <Stack direction="row" sx={{ gap: 1, flexWrap: 'wrap' }}>
              {specialties.map((value) => (
                <Chip
                  key={value}
                  label={t.has(`specialty_${value}`) ? t(`specialty_${value}`) : value}
                  sx={{ fontWeight: 500, backgroundColor: 'var(--bal-primary-soft)', color: 'var(--bal-primary)' }}
                />
              ))}
            </Stack>
          ) : (
            <Typography variant="caption" sx={{ color: 'text.secondary' }}>
              {t('summary_none')}
            </Typography>
          )}
        </FormSection>

        {/* Optional registry details the admin cross-checks — issue/expiry feed the credential-expiry
            sweep, so wrong dates are a correctness risk; a Jalali picker replaces the Gregorian-only
            native input. */}
        {editingIno ? (
          <FormSection
            title={t('registry_details_title')}
            description={t('registry_details_description')}
            icon="audit"
            optional
            optionalLabel={tc('optional')}
          >
            <RhfTextField<CredentialsFormValues> name="issuingAuthority" label={t('issuing_authority_label')} fullWidth />
            <Stack direction="row" sx={{ gap: 1.5, flexWrap: 'wrap' }}>
              <RhfJalaliDateField<CredentialsFormValues>
                name="issuedAt"
                label={t('issued_at_label')}
                max={expiresAt ?? undefined}
                sx={{ flex: 1, minWidth: 160 }}
              />
              <RhfJalaliDateField<CredentialsFormValues>
                name="expiresAt"
                label={t('expires_at_label')}
                min={issuedAt ?? undefined}
                sx={{ flex: 1, minWidth: 160 }}
              />
            </Stack>
          </FormSection>
        ) : issuingAuthority || issuedAt || expiresAt ? (
          <FormSection title={t('registry_details_title')} icon="audit">
            {issuingAuthority ? <Typography variant="body2">{issuingAuthority}</Typography> : null}
            {issuedAt || expiresAt ? (
              <Typography variant="caption" sx={{ color: 'text.secondary' }}>
                {issuedAt ? formatShamsiDate(issuedAt, locale) : ''}
                {issuedAt && expiresAt ? ' – ' : ''}
                {expiresAt ? formatShamsiDate(expiresAt, locale) : ''}
              </Typography>
            ) : null}
          </FormSection>
        ) : null}

        <Paper
          elevation={0}
          sx={{ p: 1.5, borderRadius: 'var(--bal-radius-md)', bgcolor: 'var(--bal-primary-soft)', display: 'flex', gap: 1, alignItems: 'center' }}
        >
          <AppIcon icon="info" size={18} color="var(--bal-primary)" />
          <Typography variant="caption" sx={{ color: 'text.secondary' }}>
            {t('manual_review_note')}
          </Typography>
        </Paper>

        {editingIno ? (
          <>
            {!hasAnyDocument ? (
              <Typography variant="caption" sx={{ color: 'text.secondary' }}>
                {t('credentials_needs_document')}
              </Typography>
            ) : null}
            <Stack direction="row" sx={{ gap: 1 }}>
              <AppButton
                type="submit"
                color="primary"
                variant="contained"
                startIcon="license"
                disabled={!hasAnyDocument || submitCredentials.isPending}
              >
                {submitCredentials.isPending ? t('credentials_submitting') : t('credentials_submit')}
              </AppButton>
              <AppButton variant="text" color="primary" to={`/${locale}${ROUTES.NURSE_VERIFICATION}`}>
                {t('back_to_checklist')}
              </AppButton>
            </Stack>
          </>
        ) : (
          <AppButton color="primary" variant="contained" to={`/${locale}${ROUTES.NURSE_VERIFICATION}`} sx={{ alignSelf: 'flex-start' }}>
            {t('back_to_checklist')}
          </AppButton>
        )}
      </Box>
    </FormProvider>
  );
};
