/**
 * Login Client Component
 * 
 * Handles client-side login flow using the LoginFlowController.
 * Deterministic state machine per docs/architecture/website/LOGIN_FLOW_STATE_MACHINE.md
 */

'use client';

import { useAuth } from '@/components/auth/AuthContext';
import { LoginFlowController, LoginState } from '@/lib/auth/LoginFlowController';
import { LoginViewData } from '@/lib/builders/view-data/types/LoginViewData';
import { LoginViewModelBuilder } from '@/lib/builders/view-models/LoginViewModelBuilder';
import { LoginMutation } from '@/lib/mutations/auth/LoginMutation';
import { validateLoginForm, type LoginFormValues } from '@/lib/utils/validation';
import { LoginViewModel } from '@/lib/view-models/auth/LoginViewModel';
import { LoginTemplate } from '@/templates/auth/LoginTemplate';
import { LoginLoadingTemplate } from '@/templates/auth/LoginLoadingTemplate';
import { useRouter, useSearchParams } from 'next/navigation';
import { useEffect, useMemo, useState } from 'react';
import { ClientWrapperProps } from '@/lib/contracts/components/ComponentContracts';

export function LoginClient({ viewData }: ClientWrapperProps<LoginViewData>) {
  const router = useRouter();
  const searchParams = useSearchParams();
  const { refreshSession, session } = useAuth();
  
  // Build ViewModel from ViewData
  const [viewModel, setViewModel] = useState<LoginViewModel>(() => 
    LoginViewModelBuilder.build(viewData)
  );

  // Login flow controller
  const controller = useMemo(() => {
    const returnTo = searchParams.get('returnTo') ?? '/dashboard';
    return new LoginFlowController(session, returnTo);
  }, [session, searchParams]);

  // Check controller state on mount and session changes
  useEffect(() => {
    const action = controller.getNextAction();
    
    if (action.type === 'REDIRECT') {
      router.replace(action.path);
    }
  }, [controller, router]);

  // Handle form field changes
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { name, value, type } = e.target;
    const checked = 'checked' in e.target ? e.target.checked : false;
    const fieldValue = type === 'checkbox' ? checked : value;

    setViewModel(prev => {
      const newFormState = {
        ...prev.formState,
        fields: {
          ...prev.formState.fields,
          [name]: {
            ...prev.formState.fields[name as keyof typeof prev.formState.fields],
            value: fieldValue,
            touched: true,
            error: undefined,
          },
        },
      };
      return prev.withFormState(newFormState);
    });
  };

  // Handle form submission
  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();

    const values: LoginFormValues = {
      email: viewModel.formState.fields.email.value as string,
      password: viewModel.formState.fields.password.value as string,
      rememberMe: viewModel.formState.fields.rememberMe.value as boolean,
    };

    // Validate form
    const errors = validateLoginForm(values);
    const hasErrors = Object.keys(errors).length > 0;

    if (hasErrors) {
      setViewModel(prev => {
        const newFormState = {
          ...prev.formState,
          isValid: false,
          submitCount: prev.formState.submitCount + 1,
          fields: {
            ...prev.formState.fields,
            email: {
              ...prev.formState.fields.email,
              error: errors.email,
              touched: true,
            },
            password: {
              ...prev.formState.fields.password,
              error: errors.password,
              touched: true,
            },
          },
        };
        return prev.withFormState(newFormState);
      });
      return;
    }

    // Update submitting state
    setViewModel(prev => prev.withMutationState(true, null));

    try {
      // Execute login mutation
      const mutation = new LoginMutation();
      const result = await mutation.execute({
        email: values.email,
        password: values.password,
        rememberMe: values.rememberMe,
      });

      if (result.isErr()) {
        const error = result.getError();
        setViewModel(prev => {
          const newFormState = {
            ...prev.formState,
            isSubmitting: false,
            submitError: error,
          };
          return prev.withFormState(newFormState).withMutationState(false, error);
        });
        
        if (process.env.NODE_ENV === 'development') {
          setViewModel(prev => prev.withUIState({
            ...prev.uiState,
            showErrorDetails: true,
          }));
        }
        return;
      }

      // Success - refresh session and transition
      await refreshSession();
      
      // Transition to post-auth state
      controller.transitionToPostAuth();
      const action = controller.getNextAction();
      
      if (action.type === 'REDIRECT') {
        router.push(action.path);
      }
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Login failed';
      setViewModel(prev => {
        const newFormState = {
          ...prev.formState,
          isSubmitting: false,
          submitError: errorMessage,
        };
        return prev.withFormState(newFormState).withMutationState(false, errorMessage);
      });
      
      if (process.env.NODE_ENV === 'development') {
        setViewModel(prev => prev.withUIState({
          ...prev.uiState,
          showErrorDetails: true,
        }));
      }
    }
  };

  // Toggle password visibility
  const togglePassword = () => {
    setViewModel(prev => prev.withUIState({
      ...prev.uiState,
      showPassword: !prev.uiState.showPassword,
    }));
  };

  // Get current state from controller
  const state = controller.getState();
  
  // If user is authenticated with permissions, show loading
  if (state === LoginState.AUTHENTICATED_WITH_PERMISSIONS) {
    return <LoginLoadingTemplate viewData={{}} />;
  }

  // If user has insufficient permissions, show permission error
  if (state === LoginState.AUTHENTICATED_WITHOUT_PERMISSIONS) {
    return (
      <LoginTemplate
        viewData={{
          ...viewData,
          hasInsufficientPermissions: true,
          showPassword: viewModel.showPassword,
          showErrorDetails: viewModel.showErrorDetails,
          formState: viewModel.formState,
          isSubmitting: viewModel.isSubmitting,
          submitError: viewModel.submitError,
        }}
        formActions={{
          handleChange,
          handleSubmit,
          setFormState: (state) => {
            if (typeof state === 'function') {
              const newState = state(viewModel.formState);
              setViewModel(prev => prev.withFormState(newState));
            } else {
              setViewModel(prev => prev.withFormState(state));
            }
          },
          setShowPassword: togglePassword,
          setShowErrorDetails: (show) => {
            setViewModel(prev => prev.withUIState({
              ...prev.uiState,
              showErrorDetails: show,
            }));
          },
        }}
        mutationState={{
          isPending: viewModel.mutationPending,
          error: viewModel.mutationError,
        }}
      />
    );
  }

  // Show login form
  return (
    <LoginTemplate
      viewData={{
        ...viewData,
        showPassword: viewModel.showPassword,
        showErrorDetails: viewModel.showErrorDetails,
        formState: viewModel.formState,
        isSubmitting: viewModel.isSubmitting,
        submitError: viewModel.submitError,
      }}
      formActions={{
        handleChange,
        handleSubmit,
        setFormState: (state) => {
          if (typeof state === 'function') {
            const newState = state(viewModel.formState);
            setViewModel(prev => prev.withFormState(newState));
          } else {
            setViewModel(prev => prev.withFormState(state));
          }
        },
        setShowPassword: togglePassword,
        setShowErrorDetails: (show) => {
          setViewModel(prev => prev.withUIState({
            ...prev.uiState,
            showErrorDetails: show,
          }));
        },
      }}
      mutationState={{
        isPending: viewModel.mutationPending,
        error: viewModel.mutationError,
      }}
    />
  );
}
