import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { handleError, handleSuccess, AppError, getErrorMessage } from '@/lib/errorHandler';
import { logger } from '@/lib/logger';
import { supabase } from '@/integrations/supabase/client';
import { Loader2, Mail, CheckCircle2, AlertCircle } from 'lucide-react';
import { TurnstileCaptcha } from '@/components/auth/TurnstileCaptcha';
import { useTheme } from '@/components/theme/ThemeProvider';
import { notificationService } from '@/lib/notificationService';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { validateEmailNotDisposable } from '@/lib/emailValidation';

const emailSchema = z.object({
  currentPassword: z.string().min(1, 'Current password is required'),
  newEmail: z.string().email('Please enter a valid email address'),
  confirmEmail: z.string().email('Please enter a valid email address'),
}).refine((data) => data.newEmail === data.confirmEmail, {
  message: "Email addresses don't match",
  path: ["confirmEmail"],
});

type EmailFormData = z.infer<typeof emailSchema>;

type Step = 'verification' | 'success';

interface EmailChangeDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  currentEmail: string;
  userId: string;
}

export function EmailChangeDialog({ open, onOpenChange, currentEmail, userId }: EmailChangeDialogProps) {
  const { theme } = useTheme();
  const [step, setStep] = useState<Step>('verification');
  const [loading, setLoading] = useState(false);
  const [captchaToken, setCaptchaToken] = useState<string>('');
  const [captchaKey, setCaptchaKey] = useState(0);

  const form = useForm<EmailFormData>({
    resolver: zodResolver(emailSchema),
    defaultValues: {
      currentPassword: '',
      newEmail: '',
      confirmEmail: '',
    },
  });

  const handleClose = () => {
    if (loading) return;
    
    onOpenChange(false);
    setTimeout(() => {
      setStep('verification');
      form.reset();
      setCaptchaToken('');
      setCaptchaKey(prev => prev + 1);
    }, 300);
  };

  const onSubmit = async (data: EmailFormData) => {
    if (!captchaToken) {
      handleError(
        new AppError('Please complete the CAPTCHA verification.', 'CAPTCHA_REQUIRED'),
        { action: 'Change email', userId, metadata: { step: 'captcha_validation' } }
      );
      return;
    }

    if (data.newEmail.toLowerCase() === currentEmail.toLowerCase()) {
      handleError(
        new AppError('The new email is the same as your current email.', 'SAME_EMAIL'),
        { action: 'Change email', userId, metadata: { currentEmail, newEmail: data.newEmail } }
      );
      return;
    }

    // Phase 4: AAL2 check for security-critical operations
    const { data: { session } } = await supabase.auth.getSession();
    if (session) {
      // Check if user has MFA enrolled
      const { data: factorsData } = await supabase.auth.mfa.listFactors();
      const hasMFA = factorsData?.totp?.some(f => f.status === 'verified') || false;
      
      if (hasMFA) {
        const jwt = session.access_token;
        const payload = JSON.parse(atob(jwt.split('.')[1]));
        const currentAal = payload.aal || 'aal1';
        
        if (currentAal !== 'aal2') {
          handleError(
            new AppError(
              'Please verify your identity with MFA first',
              'AAL2_REQUIRED'
            ),
            { action: 'Change email', userId, metadata: { step: 'aal2_check' } }
          );
          sessionStorage.setItem('mfa_step_up_required', 'true');
          sessionStorage.setItem('mfa_intended_path', '/settings?tab=security');
          window.location.href = '/auth';
          return;
        }
      }
    }

    setLoading(true);
    try {
      // Step 1: Validate email is not disposable
      const emailValidation = await validateEmailNotDisposable(data.newEmail);

      if (!emailValidation.valid) {
        handleError(
          new AppError(
            emailValidation.reason || "Please use a permanent email address",
            'DISPOSABLE_EMAIL'
          ),
          { action: 'Validate email', userId, metadata: { email: data.newEmail } }
        );
        setLoading(false);
        return;
      }

      // Step 2: Reauthenticate with current password
      const { error: signInError } = await supabase.auth.signInWithPassword({
        email: currentEmail,
        password: data.currentPassword,
        options: {
          captchaToken
        }
      });
      
      if (signInError) {
        // Reset CAPTCHA on authentication failure
        setCaptchaToken('');
        setCaptchaKey(prev => prev + 1);
        throw signInError;
      }

      // Step 3: Update email address
      // Supabase will send verification emails to both old and new addresses
      const { error: updateError } = await supabase.auth.updateUser({
        email: data.newEmail
      });

      if (updateError) throw updateError;

      // Step 4: Novu subscriber will be updated automatically after both emails are confirmed
      // This happens in the useAuth hook when the email change is fully verified

      // Step 5: Log the email change attempt
      supabase.from('admin_audit_log').insert({
        admin_user_id: userId,
        target_user_id: userId,
        action: 'email_change_initiated',
        details: {
          old_email: currentEmail,
          new_email: data.newEmail,
          timestamp: new Date().toISOString(),
        }
      }).then(({ error }) => {
        if (error) {
          logger.error('Failed to log email change', {
            userId,
            action: 'email_change_audit_log',
            error: error.message
          });
        }
      });

      // Step 6: Send security notifications (non-blocking)
      if (notificationService.isEnabled()) {
        notificationService.trigger({
          workflowId: 'security-alert',
          subscriberId: userId,
          payload: {
            alert_type: 'email_change_initiated',
            old_email: currentEmail,
            new_email: data.newEmail,
            timestamp: new Date().toISOString(),
          }
        }).catch(error => {
          logger.error('Failed to send security notification', {
            userId,
            action: 'email_change_notification',
            error: error instanceof Error ? error.message : String(error)
          });
        });
      }

      handleSuccess(
        'Email change initiated',
        'Check both email addresses for confirmation links.'
      );
      
      setStep('success');
    } catch (error: unknown) {
      const errorMsg = getErrorMessage(error);
      logger.error('Email change failed', {
        userId,
        action: 'email_change',
        error: errorMsg,
      });

      const hasMessage = error instanceof Error || (typeof error === 'object' && error !== null && 'message' in error);
      const hasStatus = typeof error === 'object' && error !== null && 'status' in error;
      const errorMessage = hasMessage ? (error as { message: string }).message : '';
      const errorStatus = hasStatus ? (error as { status: number }).status : 0;

      if (errorMessage.includes('rate limit') || errorStatus === 429) {
        handleError(
          new AppError(
            'Please wait a few minutes before trying again.',
            'RATE_LIMIT',
            'Too many email change attempts'
          ),
          { action: 'Change email', userId, metadata: { currentEmail, newEmail: data.newEmail } }
        );
      } else if (errorMessage.includes('Invalid login credentials')) {
        handleError(
          new AppError(
            'The password you entered is incorrect.',
            'INVALID_PASSWORD',
            'Incorrect password during email change'
          ),
          { action: 'Verify password', userId }
        );
      } else {
        handleError(
          error,
          { 
            action: 'Change email', 
            userId, 
            metadata: { 
              currentEmail, 
              newEmail: data.newEmail,
              errorType: error instanceof Error ? error.constructor.name : 'Unknown'
            } 
          }
        );
      }
    } finally {
      setLoading(false);
    }
  };

  return (
    <Dialog open={open} onOpenChange={handleClose}>
      <DialogContent className="sm:max-w-[500px]">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <Mail className="w-5 h-5" />
            Change Email Address
          </DialogTitle>
          <DialogDescription>
            {step === 'verification' ? (
              'Enter your current password and new email address to proceed.'
            ) : (
              'Verification emails have been sent.'
            )}
          </DialogDescription>
        </DialogHeader>

        {step === 'verification' ? (
          <Form {...form}>
            <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
              <Alert>
                <AlertCircle className="h-4 w-4" />
                <AlertDescription>
                  Current email: <strong>{currentEmail}</strong>
                </AlertDescription>
              </Alert>

              <FormField
                control={form.control}
                name="currentPassword"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>Current Password *</FormLabel>
                    <FormControl>
                      <Input
                        type="password"
                        placeholder="Enter your current password"
                        disabled={loading}
                        {...field}
                      />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />

              <FormField
                control={form.control}
                name="newEmail"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>New Email Address *</FormLabel>
                    <FormControl>
                      <Input
                        type="email"
                        placeholder="Enter your new email"
                        disabled={loading}
                        {...field}
                      />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />

              <FormField
                control={form.control}
                name="confirmEmail"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>Confirm New Email *</FormLabel>
                    <FormControl>
                      <Input
                        type="email"
                        placeholder="Confirm your new email"
                        disabled={loading}
                        {...field}
                      />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />

              <div className="space-y-2">
                <TurnstileCaptcha
                  key={captchaKey}
                  onSuccess={setCaptchaToken}
                  onError={() => setCaptchaToken('')}
                  onExpire={() => setCaptchaToken('')}
                  siteKey={import.meta.env.VITE_TURNSTILE_SITE_KEY}
                  theme={theme === 'dark' ? 'dark' : 'light'}
                  size="normal"
                />
              </div>

              <DialogFooter>
                <Button type="button" variant="outline" onClick={handleClose} disabled={loading}>
                  Cancel
                </Button>
                <Button type="submit" disabled={loading || !captchaToken}>
                  {loading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
                  Change Email
                </Button>
              </DialogFooter>
            </form>
          </Form>
        ) : (
          <div className="space-y-6">
            <div className="flex flex-col items-center justify-center text-center space-y-4 py-6">
              <div className="rounded-full bg-primary/10 p-3">
                <CheckCircle2 className="w-8 h-8 text-primary" />
              </div>
              <div className="space-y-2">
                <h3 className="font-semibold text-lg">Verification Required</h3>
                <p className="text-sm text-muted-foreground max-w-md">
                  We've sent verification emails to both your current email address (<strong>{currentEmail}</strong>) 
                  and your new email address (<strong>{form.getValues('newEmail')}</strong>).
                </p>
              </div>
            </div>

            <Alert>
              <Mail className="h-4 w-4" />
              <AlertDescription>
                <strong>Important:</strong> You must click the confirmation link in BOTH emails to complete 
                the email change. Your email address will not change until both verifications are confirmed.
              </AlertDescription>
            </Alert>

            <DialogFooter>
              <Button onClick={handleClose} className="w-full">
                Close
              </Button>
            </DialogFooter>
          </div>
        )}
      </DialogContent>
    </Dialog>
  );
}
