import { useCallback, useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { getCurrentUser, signIn, signOut as signOutRequest } from '@/shared/api/auth';
import { AuthExpiredError } from '@/shared/api/httpClient';
import {
  AUTH_MODAL_SIGNIN_CLOSE_DELAY_MS,
  AUTH_MODAL_SIGNUP_CLOSE_DELAY_MS,
} from '@/shared/constants/auth';
import { APP_ROUTE_PATHS } from '@/shared/constants/routes';
import { CurrentUser } from '@/shared/types/auth';
import { StaffProfile } from '@/shared/types/app';
import { toStaffProfile } from '@/business/auth/mappers';
import { useCampusCatalog } from '@/business/campuses/hooks';
import { AuthActionResult, AuthSessionState } from '@/business/auth/types';
import { getErrorMessage, getOptionalErrorMessage } from '@/shared/errors/errorMessages';
import type {
  AuthModalDraft,
  AuthModalMode,
  AuthModalWorkflowInput,
  AuthSignupStep,
} from '@/business/auth/types';
import {
  getNextSignupStep,
  getPreviousSignupStep,
  getSignupCampusName,
  validateSignupStepOne,
} from '@/business/auth/selectors';
import type { CampusId, UserRole } from '@/shared/types/app';

export function useAuthSession(): AuthSessionState {
  const navigate = useNavigate();
  const [user, setUser] = useState<CurrentUser | null>(null);
  const [loading, setLoading] = useState(true);

  const clearSession = useCallback(() => {
    setUser(null);
  }, []);

  const redirectToLogin = useCallback(() => {
    navigate(APP_ROUTE_PATHS.login, { replace: true });
  }, [navigate]);

  useEffect(() => {
    let isActive = true;

    void getCurrentUser()
      .then((currentUser) => {
        if (isActive) {
          setUser(currentUser);
        }
      })
      .catch((error: unknown) => {
        if (isActive) {
          clearSession();
          if (error instanceof AuthExpiredError) {
            redirectToLogin();
          }
        }
      })
      .finally(() => {
        if (isActive) {
          setLoading(false);
        }
      });

    return () => {
      isActive = false;
    };
  }, [clearSession, redirectToLogin]);

  const handleSignIn = useCallback(async (email: string, password: string): Promise<AuthActionResult> => {
    setLoading(true);

    try {
      const currentUser = await signIn({ email, password });
      setUser(currentUser);
      return { error: null };
    } catch (error) {
      clearSession();
      if (error instanceof AuthExpiredError) {
        redirectToLogin();
      }
      return { error: getErrorMessage(error, 'Sign in failed') };
    } finally {
      setLoading(false);
    }
  }, [clearSession, redirectToLogin]);

  const signUp = useCallback(async (): Promise<AuthActionResult> => ({
    error:
      'Account creation is not available until backend product roles, campus assignment, and staff profile creation are implemented.',
  }), []);

  const signOut = useCallback(async (): Promise<AuthActionResult> => {
    try {
      await signOutRequest();
      clearSession();
      return { error: null };
    } catch (error) {
      if (error instanceof AuthExpiredError) {
        clearSession();
        redirectToLogin();
        return { error: null };
      }
      return { error: getErrorMessage(error, 'Sign out failed') };
    }
  }, [clearSession, redirectToLogin]);

  const updateProfile = useCallback(async (): Promise<AuthActionResult> => ({
    error: 'Profile updates are not available until backend staff profile updates are implemented.',
  }), []);

  const profile: StaffProfile | null = useMemo(() => (user ? toStaffProfile(user) : null), [user]);

  return {
    user,
    profile,
    loading,
    signIn: handleSignIn,
    signUp,
    signOut,
    updateProfile,
    isAuthenticated: Boolean(user),
  };
}

const initialAuthModalDraft: AuthModalDraft = {
  email: '',
  password: '',
  confirmPassword: '',
  fullName: '',
  role: 'teacher',
  campus: '',
  showPassword: false,
};

export function useAuthModalWorkflow({
  signIn: signInAction,
  signUp: signUpAction,
  onClose,
}: AuthModalWorkflowInput) {
  const campusCatalog = useCampusCatalog();
  const [mode, setMode] = useState<AuthModalMode>('signin');
  const [signupStep, setSignupStep] = useState<AuthSignupStep>(1);
  const [draft, setDraft] = useState<AuthModalDraft>(initialAuthModalDraft);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState<string | null>(null);

  const resetForm = useCallback(() => {
    setDraft(initialAuthModalDraft);
    setError(null);
    setSuccess(null);
    setMode('signin');
    setSignupStep(1);
  }, []);

  const closeAfterSuccess = useCallback((delayMs: number) => {
    window.setTimeout(() => {
      onClose();
      resetForm();
    }, delayMs);
  }, [onClose, resetForm]);

  const updateDraft = useCallback((patch: Partial<AuthModalDraft>) => {
    setDraft((currentDraft) => ({ ...currentDraft, ...patch }));
  }, []);

  const handleSignIn = useCallback(async () => {
    setError(null);
    setSuccess(null);
    setLoading(true);

    const result = await signInAction(draft.email, draft.password);
    setLoading(false);

    if (result.error) {
      setError(result.error);
      return;
    }

    setSuccess('Signed in successfully!');
    closeAfterSuccess(AUTH_MODAL_SIGNIN_CLOSE_DELAY_MS);
  }, [closeAfterSuccess, draft.email, draft.password, signInAction]);

  const handleSignUp = useCallback(async () => {
    setError(null);
    setSuccess(null);

    const campusName = getSignupCampusName(draft.campus, campusCatalog.campuses);

    if (!campusName) {
      setError(campusCatalog.error ? 'Campus list is unavailable. Please try again.' : 'Please select your campus mascot');
      return;
    }

    setLoading(true);
    const result = await signUpAction(draft.email, draft.password, draft.fullName, draft.role, campusName);
    setLoading(false);

    if (result.error) {
      setError(result.error);
      return;
    }

    setSuccess('Account created! You are now signed in.');
    closeAfterSuccess(AUTH_MODAL_SIGNUP_CLOSE_DELAY_MS);
  }, [
    campusCatalog.campuses,
    campusCatalog.error,
    closeAfterSuccess,
    draft.campus,
    draft.email,
    draft.fullName,
    draft.password,
    draft.role,
    signUpAction,
  ]);

  const goToNextStep = useCallback(() => {
    setError(null);

    if (signupStep === 1) {
      const validationError = validateSignupStepOne(draft);
      if (validationError) {
        setError(validationError);
        return;
      }
      setSignupStep(2);
      return;
    }

    if (signupStep === 2) {
      setSignupStep(3);
      return;
    }

    void handleSignUp();
  }, [draft, handleSignUp, signupStep]);

  const goToPreviousStep = useCallback(() => {
    setError(null);
    setSignupStep((currentStep) => getPreviousSignupStep(currentStep));
  }, []);

  const handleClose = useCallback(() => {
    resetForm();
    onClose();
  }, [onClose, resetForm]);

  const switchMode = useCallback((nextMode: AuthModalMode) => {
    setMode(nextMode);
    setError(null);
    setSuccess(null);
    setSignupStep(1);
  }, []);

  const selectedCampusId = draft.campus;

  return {
    state: {
      mode,
      signupStep,
      draft,
      loading,
      error,
      success,
      selectedCampusId,
      campuses: campusCatalog.campuses,
      campusesLoading: campusCatalog.isLoading,
      campusesError: getOptionalErrorMessage(campusCatalog.error),
    },
    actions: {
      updateDraft,
      setRole: (role: UserRole) => updateDraft({ role }),
      setCampus: (campus: CampusId | '') => updateDraft({ campus }),
      setShowPassword: (showPassword: boolean) => updateDraft({ showPassword }),
      handleSignIn,
      goToNextStep,
      goToPreviousStep,
      handleClose,
      switchMode,
      getNextSignupStep,
    },
  };
}
