'use client';
import { useMemo, useState } from 'react';
import { useLocale, useTranslations } from 'next-intl';
import { useRouter } from 'next/navigation';
import { useSnackbar } from 'notistack';
import { Box, Chip, Paper, Stack, TextField, Typography } from '@mui/material';
import { AppButton, AppIcon, AppLoading, DocumentUpload, JalaliDateField } 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 { 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'];

/**
 * 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).
 *
 * Hydrates from `status.credentialSubmission` (REQ-056, mock-tolerant): 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 — no dead
 * disabled button, because there is no button to be dead.
 */
export default function CredentialsSubmitPage() {
  const t = useTranslations('verification');
  const locale = useLocale();
  const router = useRouter();
  const { enqueueSnackbar } = useSnackbar();

  const { data: status, isLoading } = useVerificationStatus();
  const uploadDocument = useUploadVerificationDocument();
  const submitCredentials = useSubmitCredentials();

  const submission = status?.credentialSubmission;

  const [inoNumber, setInoNumber] = useState('');
  const [inoError, setInoError] = useState(false);
  const [editingIno, setEditingIno] = useState(true);
  const [specialties, setSpecialties] = useState<string[]>([]);
  const [customSpecialty, setCustomSpecialty] = useState('');
  const [issuingAuthority, setIssuingAuthority] = useState('');
  const [issuedAt, setIssuedAt] = useState<string | null>(null);
  const [expiresAt, setExpiresAt] = useState<string | null>(null);
  const [uploadedSteps, setUploadedSteps] = useState<Record<number, boolean>>({});
  const [hydrated, setHydrated] = useState(false);

  // Hydrate once from the server's read-back, adjusted directly during render (never in an effect —
  // that would cascade an extra render) — and never overwrite what the nurse is actively editing.
  if (!hydrated && submission) {
    setHydrated(true);
    setEditingIno(!submission.inoNumberSubmitted);
    setSpecialties(submission.specialties);
    setIssuingAuthority(submission.issuingAuthority ?? '');
    setIssuedAt(submission.issuedAt ?? null);
    setExpiresAt(submission.expiresAt ?? null);
  }

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

  const toggleSpecialty = (value: string) =>
    setSpecialties((prev) => (prev.includes(value) ? prev.filter((item) => item !== value) : [...prev, value]));

  const addCustomSpecialty = () => {
    const value = customSpecialty.trim();
    if (value && !specialties.includes(value)) setSpecialties((prev) => [...prev, value]);
    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;
  };

  const handleSubmit = () => {
    const inoValid = inoNumber.trim().length > 0;
    setInoError(!inoValid);
    if (!inoValid) return;

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

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

  // 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 hasAnyDocument =
    Object.values(uploadedSteps).some(Boolean) ||
    manualSteps.some((step) => step.status === 'in_review' || step.status === 'passed');
  const canSubmit = hasAnyDocument && !submitCredentials.isPending;

  return (
    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3, maxWidth: CONTENT_MAX_WIDTH, mx: 'auto', width: '100%' }}>
      <VerificationJourneyHeader group="credentials" />

      <Box>
        <Typography variant="h6" component="h2" sx={{ fontWeight: 700 }}>
          {t('credentials_title')}
        </Typography>
        <Typography variant="body2" sx={{ color: 'text.secondary' }}>
          {t('credentials_subtitle')}
        </Typography>
      </Box>

      {editingIno ? (
        <TextField
          label={t('ino_number_label')}
          value={inoNumber}
          onChange={(event) => {
            setInoNumber(event.target.value);
            if (inoError) setInoError(false);
          }}
          error={inoError}
          helperText={inoError ? t('ino_number_required') : t('ino_number_hint')}
          slotProps={{ htmlInput: { dir: 'ltr', style: { textAlign: 'start' } } }}
          fullWidth
        />
      ) : (
        <Stack
          direction="row"
          sx={{ gap: 1, alignItems: 'center', justifyContent: 'space-between', p: 1.5, borderRadius: 2, 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>
      )}

      {/* 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. */}
      <Stack sx={{ gap: 2 }}>
        {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}
          />
        ))}
      </Stack>

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

      <Stack sx={{ gap: 1 }}>
        <Typography variant="subtitle2" sx={{ fontWeight: 700 }}>
          {t('specialties_label')}
        </Typography>
        {editingIno ? (
          <>
            <Typography variant="caption" sx={{ color: 'text.secondary' }}>
              {t('specialties_hint')}
            </Typography>
            <Stack direction="row" sx={{ gap: 1, flexWrap: 'wrap' }}>
              {SPECIALTY_PRESETS.map((preset) => {
                const selected = specialties.includes(preset);
                return (
                  <Chip
                    key={preset}
                    label={t.has(`specialty_${preset}`) ? t(`specialty_${preset}`) : preset}
                    onClick={() => toggleSpecialty(preset)}
                    icon={selected ? <AppIcon icon="verified" size={16} color="var(--bal-primary-contrast)" /> : undefined}
                    variant={selected ? 'filled' : 'outlined'}
                    sx={{
                      fontWeight: 500,
                      backgroundColor: selected ? 'var(--bal-primary)' : 'transparent',
                      color: selected ? 'var(--bal-primary-contrast)' : 'var(--bal-primary)',
                      borderColor: 'var(--bal-primary)',
                    }}
                  />
                );
              })}
              {specialties
                .filter((value) => !SPECIALTY_PRESETS.includes(value))
                .map((value) => (
                  <Chip
                    key={value}
                    label={value}
                    onDelete={() => toggleSpecialty(value)}
                    sx={{ fontWeight: 500, backgroundColor: 'var(--bal-primary)', color: 'var(--bal-primary-contrast)' }}
                  />
                ))}
            </Stack>
            <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>
        )}
      </Stack>

      {/* 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 ? (
        <Stack sx={{ gap: 1.5 }}>
          <Typography variant="subtitle2" sx={{ fontWeight: 700 }}>
            {t('registry_details_label')}
          </Typography>
          <TextField
            label={t('issuing_authority_label')}
            value={issuingAuthority}
            onChange={(event) => setIssuingAuthority(event.target.value)}
            fullWidth
          />
          <Stack direction="row" sx={{ gap: 1.5, flexWrap: 'wrap' }}>
            <JalaliDateField
              label={t('issued_at_label')}
              value={issuedAt}
              onChange={setIssuedAt}
              max={expiresAt ?? undefined}
              sx={{ flex: 1, minWidth: 160 }}
            />
            <JalaliDateField
              label={t('expires_at_label')}
              value={expiresAt}
              onChange={setExpiresAt}
              min={issuedAt ?? undefined}
              sx={{ flex: 1, minWidth: 160 }}
            />
          </Stack>
        </Stack>
      ) : issuingAuthority || issuedAt || expiresAt ? (
        <Stack sx={{ gap: 0.5 }}>
          <Typography variant="subtitle2" sx={{ fontWeight: 700 }}>
            {t('registry_details_label')}
          </Typography>
          {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}
        </Stack>
      ) : null}

      <Paper
        elevation={0}
        sx={{ p: 1.5, borderRadius: 2, 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 color="primary" variant="contained" startIcon="license" onClick={handleSubmit} disabled={!canSubmit}>
              {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>
  );
}
