/**
 * VendorUpgradeFormShell — authenticated-user vendor upgrade orchestrator
 * (FDS §5.1).
 *
 * Routes between three step views:
 *   1. <PhoneStep />        — collect phone (when !hasPhone)
 *   2. <CodeStep />         — OTP verify
 *   3. <UpgradeFormStep />  — business details → POST /api/vendor/upgrade
 *
 * Holds state, wires step transitions, owns API calls. No JSX beyond logo
 * header + step router.
 */

'use client';

import { useState, useEffect, useCallback, useMemo } from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { MDLogo } from '@/components/ui/icons/MDLogo';
import { useT } from '@/lib/i18n/react';
import { getCsrfToken } from '@/lib/csrf';
import { captureCaught } from '@/lib/observability';
import { cn } from '@/lib/cn';
import { PhoneStep } from './steps/PhoneStep';
import { CodeStep } from './steps/CodeStep';
import { usePhoneVerification } from './usePhoneVerification';
import {
  UpgradeFormStep,
  UPGRADE_MAX_DESCRIPTION,
  type UpgradeFormValues,
} from './steps/UpgradeFormStep';

// ─── Props ────────────────────────────────────────────────────────────────────

export interface VendorUpgradeFormShellProps {
  /** User's current email from their account. Empty string for guests. */
  prefillEmail: string;
  /** If false, show OTP step first to collect phone. */
  hasPhone: boolean;
  /** True for guests (no session yet). Switches OTP endpoint to firebase-verify. */
  isGuest?: boolean;
  /** Platform commission percentage disclosed near ToS (from env). */
  platformFeePct: number;
}

type PhoneValues = { phone: string };
type CodeValues = { code: string };

function otpCodeSchema(invalidMsg: string) {
  return z.object({ code: z.string().regex(/^\d{4,8}$/, invalidMsg) });
}

// ─── Shell ────────────────────────────────────────────────────────────────────

type WizardStep = 'phone' | 'business';

function UpgradeStepIndicator({ activeStep }: { activeStep: WizardStep }) {
  const t = useT('vendor_upgrade');
  const steps: { id: WizardStep; label: string }[] = [
    { id: 'phone', label: t('step_phone') },
    { id: 'business', label: t('step_business') },
  ];
  const activeIndex = steps.findIndex((s) => s.id === activeStep);

  return (
    <nav aria-label={t('page_title')} className="mb-6">
      <ol className="flex items-center gap-2">
        {steps.map((step, index) => {
          const isActive = index === activeIndex;
          const isComplete = index < activeIndex;
          return (
            <li key={step.id} className="flex min-w-0 flex-1 items-center gap-2">
              <span
                className={cn(
                  'flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-xs font-semibold',
                  isActive
                    ? 'bg-mode-vendor-600 text-neutral-0'
                    : isComplete
                      ? 'bg-mode-vendor-100 text-mode-vendor-700'
                      : 'bg-surface-inset text-text-muted',
                )}
                aria-current={isActive ? 'step' : undefined}
              >
                {index + 1}
              </span>
              <span
                className={cn(
                  'truncate text-xs font-medium',
                  isActive ? 'text-mode-vendor-700' : 'text-text-muted',
                )}
              >
                {step.label}
              </span>
              {index < steps.length - 1 && (
                <span
                  className="bg-border-default mx-1 hidden h-px min-w-2 flex-1 sm:block"
                  aria-hidden="true"
                />
              )}
            </li>
          );
        })}
      </ol>
    </nav>
  );
}

function VendorUpgradeFormShellInner({
  prefillEmail,
  hasPhone,
  isGuest = false,
  platformFeePct,
}: VendorUpgradeFormShellProps) {
  const t = useT('vendor_upgrade');
  const tAuth = useT('auth_flow');
  const tCommon = useT('common');
  const otpEndpoint = isGuest ? '/api/auth/firebase-verify' : '/api/auth/attach-phone';

  const phoneSchema = useMemo(
    () =>
      z.object({
        phone: z.string().trim().min(9, t('err_phone_required')).max(15),
      }),
    [t],
  );

  const upgradeSchema = useMemo(
    () =>
      z.object({
        businessName: z.string().trim().min(1, t('err_business_name_required')).max(120),
        displayName: z.string().trim().min(1, t('err_display_name_required')).max(80),
        description: z.string().max(UPGRADE_MAX_DESCRIPTION).optional(),
        businessTypeIds: z.array(z.uuid()).min(1, t('err_business_type_required')).max(5),
        businessEmail: z.email(t('err_email_invalid')),
        tosAccepted: z.literal(true, { error: t('err_tos_required') }),
      }),
    [t],
  );

  // Outer flow: 'otp' (sub-flow) → 'form' (business details)
  const [flowStep, setFlowStep] = useState<'otp' | 'form'>(hasPhone ? 'form' : 'otp');
  // OTP sub-flow
  const [otpStep, setOtpStep] = useState<'phone' | 'code'>('phone');
  const [otpApiError, setOtpApiError] = useState<string | null>(null);
  const [countryIso, setCountryIso] = useState('IL');
  // Phone OTP via Firebase → attach verified phone to the current account.
  const { recaptchaContainerRef, sending, verifying, sendCode, verifyCode } =
    usePhoneVerification(otpEndpoint);
  // Upgrade form
  const [submitError, setSubmitError] = useState<string | null>(null);
  const [displayNameTouched, setDisplayNameTouched] = useState(false);

  const phoneForm = useForm<PhoneValues>({ resolver: zodResolver(phoneSchema) });
  const codeForm = useForm<CodeValues>({
    resolver: zodResolver(otpCodeSchema(tAuth('invalid_code'))),
  });
  const upgradeForm = useForm<UpgradeFormValues>({
    resolver: zodResolver(upgradeSchema),
    defaultValues: {
      businessName: '',
      displayName: '',
      description: '',
      businessTypeIds: [] as string[],
      businessEmail: prefillEmail,
      tosAccepted: undefined as unknown as true,
    },
  });
  const { control, setValue } = upgradeForm;

  // Auto-fill displayName from businessName while untouched
  const businessNameValue = useWatch({ control, name: 'businessName' });
  useEffect(() => {
    if (!displayNameTouched) {
      setValue('displayName', businessNameValue, { shouldValidate: false });
    }
  }, [businessNameValue, displayNameTouched, setValue]);

  const descriptionValue = useWatch({ control, name: 'description' });
  const descLength = descriptionValue?.length ?? 0;

  const handleDisplayNameChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    setDisplayNameTouched(true);
    void e;
  }, []);

  // Map Firebase phone-auth error codes → auth_flow i18n keys.
  function mapOtpError(code: string | undefined): string {
    switch (code) {
      case 'auth/invalid-phone-number':
        return tAuth('invalid_phone');
      case 'auth/code-expired':
        return tAuth('otp_expired');
      case 'auth/too-many-requests':
        return tAuth('rate_limited');
      case 'auth/invalid-verification-code':
        return tAuth('invalid_code');
      default:
        return tCommon('error');
    }
  }

  async function onPhoneSubmit(v: PhoneValues) {
    setOtpApiError(null);
    const r = await sendCode(v.phone, countryIso);
    if (!r.ok) {
      setOtpApiError(mapOtpError(r.code));
      return;
    }
    setOtpStep('code');
  }

  async function onCodeSubmit(v: CodeValues) {
    setOtpApiError(null);
    const r = await verifyCode(v.code);
    if (!r.ok) {
      // attach-phone surfaces PHONE_TAKEN etc. via `error`; Firebase failures via `code`.
      setOtpApiError(r.error ?? mapOtpError(r.code));
      return;
    }
    setFlowStep('form');
  }

  function onCodeBack() {
    setOtpStep('phone');
    setOtpApiError(null);
    codeForm.reset();
  }

  async function onUpgradeSubmit(values: UpgradeFormValues) {
    setSubmitError(null);
    try {
      const res = await fetch('/api/vendor/upgrade', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
        body: JSON.stringify(values),
      });
      const data = (await res.json()) as { ok: boolean; code?: string; error?: string };
      if (!data.ok) {
        if (data.code === 'ALREADY_VENDOR') {
          window.location.assign('/vendor/settings/payments');
          return;
        }
        setSubmitError(t('error_generic'));
        return;
      }
      window.location.assign('/vendor/dashboard');
    } catch (err) {
      captureCaught(err, {
        scope: 'features.vendor-onboarding.VendorUpgradeForm',
        severity: 'warning',
      });
      setSubmitError(t('error_generic'));
    }
  }

  return (
    <>
      <div className="mx-auto w-full max-w-sm" aria-labelledby="vendor-upgrade-title">
        {/* Logo + heading */}
        <div className="mb-6">
          <MDLogo className="text-mode-vendor-700" size={32} aria-hidden="true" />
          <h1
            id="vendor-upgrade-title"
            className="text-mode-vendor-700 mt-2 text-3xl leading-[var(--line-height-tight)] font-bold"
          >
            {t('page_title')}
          </h1>
          <p className="text-text-muted mt-1 text-xs">{t('for_vendors')}</p>
          <p className="text-text-secondary mt-3 text-sm">{t('subtitle')}</p>
        </div>

        <UpgradeStepIndicator activeStep={flowStep === 'otp' ? 'phone' : 'business'} />

        {flowStep === 'otp' ? (
          <div className="flex flex-col gap-4">
            <div className="mb-2">
              <h2 className="text-text-primary text-lg font-semibold">{t('otp_step_title')}</h2>
              <p className="text-text-muted mt-1 text-sm">{t('otp_step_sub')}</p>
            </div>

            {otpApiError && (
              <p role="alert" className="text-danger-600 text-sm">
                {otpApiError}
              </p>
            )}

            {otpStep === 'phone' ? (
              <PhoneStep
                form={phoneForm}
                onSubmit={onPhoneSubmit}
                sending={sending}
                recaptchaContainerRef={recaptchaContainerRef}
                countryCode={countryIso}
                onCountryCodeChange={setCountryIso}
              />
            ) : (
              <CodeStep
                form={codeForm}
                onSubmit={onCodeSubmit}
                verifying={verifying}
                onBack={onCodeBack}
              />
            )}
          </div>
        ) : (
          <UpgradeFormStep
            form={upgradeForm}
            control={control}
            isSubmitting={upgradeForm.formState.isSubmitting}
            descLength={descLength}
            submitError={submitError}
            platformFeePct={platformFeePct}
            onSubmit={onUpgradeSubmit}
            onDisplayNameChange={handleDisplayNameChange}
          />
        )}
      </div>
    </>
  );
}

// ─── Exported island ─────────────────────────────────────────────────────────

/**
 * VendorUpgradeFormShell — exported island.
 * QueryClient, LocaleProvider, ErrorBoundary provided by HydratedIsland upstream
 * (see src/pages/vendor/register.astro).
 */
export function VendorUpgradeFormShell(props: VendorUpgradeFormShellProps) {
  return <VendorUpgradeFormShellInner {...props} />;
}
