import React, { useEffect, useMemo, useState } from 'react';
import { useForm, usePage } from '@inertiajs/react';
import { useTranslation } from 'react-i18next';
import toast from 'react-hot-toast';
import { LoaderCircle, User, Mail, Lock } from 'lucide-react';
import { Dialog, DialogContent, DialogTitle, DialogDescription } from '@/components/ui/dialog';
import type { GoogleProfilePrefill } from '../marketing/checkout/types';

export interface RegisterSuccessPayload {
  user: unknown | null;
  redirect?: string | null;
  pending_purchase?: boolean;
}

interface RegisterFormProps {
  packageId?: number;
  onSuccess?: (payload: RegisterSuccessPayload) => void;
  privacyHtml: string;
  locale?: string;
  prefill?: GoogleProfilePrefill;
  onClearGoogleProfile?: () => void;
}

type RegisterFormFields = {
  email: string;
  password: string;
  password_confirmation: string;
  first_name: string;
  last_name: string;
  privacy_consent: boolean;
  terms: boolean;
  package_id: number | null;
};

const getCookieValue = (name: string): string | null => {
  if (typeof document === 'undefined') {
    return null;
  }

  const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));

  return match ? decodeURIComponent(match[1]) : null;
};

const resolveMetaCsrfToken = (): string => {
  if (typeof document === 'undefined') {
    return '';
  }

  return (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement | null)?.content ?? '';
};

export default function RegisterForm({ packageId, onSuccess, privacyHtml, locale, prefill, onClearGoogleProfile }: RegisterFormProps) {
  const [privacyOpen, setPrivacyOpen] = useState(false);
  const [hasTriedSubmit, setHasTriedSubmit] = useState(false);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [prefillApplied, setPrefillApplied] = useState(false);
  const [serverError, setServerError] = useState<string | null>(null);
  const [serverErrorType, setServerErrorType] = useState<'generic' | 'session-expired'>('generic');
  const { t } = useTranslation(['auth', 'common']);
  const page = usePage<{ errors: Record<string, string>; locale?: string; auth?: { user?: unknown | null } }>();
  const resolvedLocale = locale ?? page.props.locale ?? 'de';

  const { data, setData, errors, clearErrors, reset, setError } = useForm<RegisterFormFields>({
    email: '',
    password: '',
    password_confirmation: '',
    first_name: '',
    last_name: '',
    privacy_consent: false,
    terms: false,
    package_id: packageId || null,
  });

  useEffect(() => {
    if (hasTriedSubmit && Object.keys(errors).length > 0) {
      toast.error(Object.values(errors).join(' '));
    }
  }, [errors, hasTriedSubmit]);

  const registerEndpoint = '/checkout/register';

  const requiredStringFields: Array<keyof RegisterFormFields> = useMemo(() => (
    ['first_name', 'last_name', 'email', 'password', 'password_confirmation']
  ), []);

  const isFormValid = useMemo(() => {
    const stringsValid = requiredStringFields.every((field) => {
      const value = data[field];
      if (typeof value !== 'string') {
        return false;
      }

      return value.trim().length > 0;
    });

    if (!stringsValid) {
      return false;
    }

    const emailValid = /.+@.+\..+/.test(data.email.trim());
    const passwordsMatch = data.password === data.password_confirmation;

    return emailValid && passwordsMatch && data.privacy_consent && data.terms;
  }, [data, requiredStringFields]);

  const namePrefill = useMemo(() => {
    const rawFirst = prefill?.given_name ?? prefill?.name?.split(' ')[0] ?? '';
    const remaining = prefill?.name ? prefill.name.split(' ').slice(1).join(' ') : '';
    const rawLast = prefill?.family_name ?? remaining;

    return {
      first: rawFirst ?? '',
      last: rawLast ?? '',
    };
  }, [prefill]);

  useEffect(() => {
    if (!prefill || prefillApplied) {
      return;
    }

    if (namePrefill.first && !data.first_name) {
      setData('first_name', namePrefill.first);
    }

    if (namePrefill.last && !data.last_name) {
      setData('last_name', namePrefill.last);
    }

    if (prefill.email && !data.email) {
      setData('email', prefill.email);
    }

    setPrefillApplied(true);
  }, [prefill, namePrefill.first, namePrefill.last, data.first_name, data.last_name, data.email, prefillApplied, setData]);
      
  const submit = async (event: React.FormEvent) => {
    event.preventDefault();
    setServerError(null);
    setServerErrorType('generic');
    setHasTriedSubmit(true);
    setIsSubmitting(true);
    clearErrors();

    const metaToken = resolveMetaCsrfToken();
    const cookieToken = getCookieValue('XSRF-TOKEN');
    const body = {
      ...data,
      locale: resolvedLocale,
      package_id: data.package_id ?? packageId ?? null,
      _token: metaToken || undefined,
    };

    try {
      const response = await fetch(registerEndpoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Accept: 'application/json',
          ...(cookieToken
            ? { 'X-XSRF-TOKEN': cookieToken }
            : metaToken
              ? { 'X-CSRF-TOKEN': metaToken }
              : {}),
        },
        credentials: 'same-origin',
        body: JSON.stringify(body),
      });

      if (response.ok) {
        const json = await response.json();
        toast.success(t('register.success_toast', 'Registrierung erfolgreich'));
        onSuccess?.({
          user: json?.user ?? null,
          redirect: json?.redirect ?? null,
          pending_purchase: json?.pending_purchase ?? json?.user?.pending_purchase ?? false,
        });
        onClearGoogleProfile?.();
        reset();
        setHasTriedSubmit(false);
        return;
      }

      if (response.status === 422) {
        const json = await response.json();
        const fieldErrors = json?.errors ?? {};
        Object.entries(fieldErrors).forEach(([key, message]) => {
          if (key in data) {
            const fieldKey = key as keyof RegisterFormFields;
            const firstMessage = Array.isArray(message) ? (message[0] as string | undefined) : typeof message === 'string' ? message : undefined;
            if (firstMessage) {
              setError(fieldKey, firstMessage);
            }
          }
        });
        toast.error(t('register.validation_failed', 'Bitte pruefen Sie Ihre Eingaben.'));
        return;
      }

      if (response.status === 419) {
        const expiredMessage = t('register.session_expired_message', 'Deine Sitzung ist abgelaufen. Bitte lade die Seite neu und versuche es erneut.');
        setServerErrorType('session-expired');
        setServerError(expiredMessage);
        toast.error(expiredMessage);
        return;
      }

      let message: string | null = null;
      try {
        const json = await response.clone().json();
        message = json?.message ?? null;
      } catch {
        message = null;
      }

      const fallbackMessage = message ?? t('register.server_error_message', 'Etwas ist schiefgelaufen. Bitte versuche es erneut.');
      setServerErrorType('generic');
      setServerError(fallbackMessage);
      toast.error(fallbackMessage);
    } catch (error) {
      console.error('Register request failed', error);
      const fallbackMessage = t('register.server_error_message', 'Etwas ist schiefgelaufen. Bitte versuche es erneut.');
      setServerErrorType('generic');
      setServerError(fallbackMessage);
      toast.error(fallbackMessage);
    } finally {
      setIsSubmitting(false);
    }
  };

  useEffect(() => {
    if (!hasTriedSubmit) {
      return;
    }

    const errorKeys = Object.keys(errors);
    if (errorKeys.length === 0) {
      return;
    }

    const firstError = errorKeys[0];
    const field = document.querySelector<HTMLInputElement | HTMLTextAreaElement>(`[name="${firstError}"]`);

    if (field) {
      field.scrollIntoView({ behavior: 'smooth', block: 'center' });
      field.focus();
    }
  }, [errors, hasTriedSubmit]);

  return (
    <div className="space-y-6">
      <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
        <div className="md:col-span-1">
          <label htmlFor="first_name" className="block text-sm font-medium text-gray-700 mb-1">
            {t('register.first_name')} {t('common:required')}
          </label>
          <div className="relative">
            <User className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
            <input
              id="first_name"
              name="first_name"
              type="text"
              required
              value={data.first_name}
              onChange={(e) => {
                setData('first_name', e.target.value);
                if (e.target.value.trim() && errors.first_name) {
                  clearErrors('first_name');
                }
              }}
              className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.first_name ? 'border-red-500' : 'border-gray-300'}`}
              placeholder={t('register.first_name_placeholder')}
            />
          </div>
          {errors.first_name && <p className="text-sm text-red-600 mt-1">{errors.first_name}</p>}
        </div>

        <div className="md:col-span-1">
          <label htmlFor="last_name" className="block text-sm font-medium text-gray-700 mb-1">
            {t('register.last_name')} {t('common:required')}
          </label>
          <div className="relative">
            <User className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
            <input
              id="last_name"
              name="last_name"
              type="text"
              required
              value={data.last_name}
              onChange={(e) => {
                setData('last_name', e.target.value);
                if (e.target.value.trim() && errors.last_name) {
                  clearErrors('last_name');
                }
              }}
              className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.last_name ? 'border-red-500' : 'border-gray-300'}`}
              placeholder={t('register.last_name_placeholder')}
            />
          </div>
          {errors.last_name && <p className="text-sm text-red-600 mt-1">{errors.last_name}</p>}
        </div>

        <div className="md:col-span-2">
          <label htmlFor="email" className="block text-sm font-medium text-gray-700 mb-1">
            {t('register.email')} {t('common:required')}
          </label>
          <div className="relative">
            <Mail className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
            <input
              id="email"
              name="email"
              type="email"
              required
              value={data.email}
              onChange={(e) => {
                setData('email', e.target.value);
                if (e.target.value.trim() && errors.email) {
                  clearErrors('email');
                }
              }}
              className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.email ? 'border-red-500' : 'border-gray-300'}`}
              placeholder={t('register.email_placeholder')}
            />
          </div>
          {errors.email && <p className="text-sm text-red-600 mt-1">{errors.email}</p>}
        </div>

        <div className="md:col-span-1">
          <label htmlFor="password" className="block text-sm font-medium text-gray-700 mb-1">
            {t('register.password')} {t('common:required')}
          </label>
          <div className="relative">
            <Lock className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
            <input
              id="password"
              name="password"
              type="password"
              required
              value={data.password}
              onChange={(e) => {
                setData('password', e.target.value);
                if (e.target.value.trim() && errors.password) {
                  clearErrors('password');
                }
                if (data.password_confirmation && e.target.value === data.password_confirmation) {
                  clearErrors('password_confirmation');
                }
              }}
              className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.password ? 'border-red-500' : 'border-gray-300'}`}
              placeholder={t('register.password_placeholder')}
            />
          </div>
          {errors.password && <p className="text-sm text-red-600 mt-1">{errors.password}</p>}
        </div>

        <div className="md:col-span-1">
          <label htmlFor="password_confirmation" className="block text-sm font-medium text-gray-700 mb-1">
            {t('register.password_confirmation')} {t('common:required')}
          </label>
          <div className="relative">
            <Lock className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
            <input
              id="password_confirmation"
              name="password_confirmation"
              type="password"
              required
              value={data.password_confirmation}
              onChange={(e) => {
                setData('password_confirmation', e.target.value);
                if (e.target.value.trim() && errors.password_confirmation) {
                  clearErrors('password_confirmation');
                }
                if (data.password && e.target.value === data.password) {
                  clearErrors('password_confirmation');
                }
              }}
              className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.password_confirmation ? 'border-red-500' : 'border-gray-300'}`}
              placeholder={t('register.password_confirmation_placeholder')}
            />
          </div>
          {errors.password_confirmation && <p className="text-sm text-red-600 mt-1">{errors.password_confirmation}</p>}
        </div>

        <div className="md:col-span-2 flex items-start">
          <input
            id="privacy_consent"
            name="privacy_consent"
            type="checkbox"
            required
            checked={data.privacy_consent}
            onChange={(e) => {
              setData('privacy_consent', e.target.checked);
              setData('terms', e.target.checked);
              if (e.target.checked && errors.privacy_consent) {
                clearErrors('privacy_consent');
              }
              if (e.target.checked && errors.terms) {
                clearErrors('terms');
              }
            }}
            className="h-4 w-4 text-[#FFB6C1] focus:ring-[#FFB6C1] border-gray-300 rounded"
          />
          <label htmlFor="privacy_consent" className="ml-2 block text-sm text-gray-900">
            {t('register.privacy_consent')}{' '}
            <button
              type="button"
              onClick={() => setPrivacyOpen(true)}
              className="text-[#FFB6C1] hover:underline inline bg-transparent border-none cursor-pointer p-0 font-medium"
            >
              {t('register.privacy_policy_link')}
            </button>.
          </label>
          {errors.privacy_consent && <p className="mt-2 text-sm text-red-600">{errors.privacy_consent}</p>}
          {errors.terms && <p className="mt-2 text-sm text-red-600">{errors.terms}</p>}
        </div>
      </div>

      {Object.keys(errors).length > 0 && (
        <div className="p-4 bg-red-50 border border-red-200 rounded-md mb-6">
          <h4 className="text-sm font-medium text-red-800 mb-2">{t('register.errors_title')}</h4>
          <ul className="text-sm text-red-800 space-y-1">
            {Object.entries(errors).map(([key, value]) => (
              <li key={key} className="flex items-start">
                <span className="font-medium">{t(`register.errors.${key}`)}:</span> {value}
              </li>
            ))}
          </ul>
        </div>
      )}

      {serverError && (
        <div className="mb-6 rounded-md border border-red-200 bg-red-50 p-4 text-sm text-red-800">
          <p className="font-semibold">
            {serverErrorType === 'session-expired'
              ? t('register.session_expired_title', 'Sicherheitsprüfung abgelaufen')
              : t('register.server_error_title', 'Registrierung konnte nicht abgeschlossen werden')}
          </p>
          <p className="mt-1">{serverError}</p>
        </div>
      )}

      <button
        type="button"
        onClick={submit}
        disabled={isSubmitting || !isFormValid}
        className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-[#FFB6C1] hover:bg-[#FF69B4] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[#FFB6C1] transition duration-300 disabled:opacity-50"
      >
        {isSubmitting && <LoaderCircle className="h-4 w-4 animate-spin mr-2" />}
        {t('register.submit')}
      </button>

      <Dialog open={privacyOpen} onOpenChange={setPrivacyOpen}>
        <DialogContent className="max-w-4xl max-h-[80vh] overflow-y-auto p-0">
          <DialogTitle className="sr-only">Datenschutzerklärung</DialogTitle>
          <DialogDescription className="sr-only">Lesen Sie unsere Datenschutzerklärung.</DialogDescription>
          <div className="p-6">
            <div dangerouslySetInnerHTML={{ __html: privacyHtml }} />
          </div>
        </DialogContent>
      </Dialog>
    </div>
  );
}
