import {
  createContext,
  useContext,
  useState,
  useCallback,
  useEffect,
  type ReactNode,
} from 'react';
import api, { setAccessToken } from '../api/client';

interface User {
  id: string;
  email: string;
  firstName: string;
  lastName: string;
  avatar?: string | null;
  phone?: string | null;
  mobile?: string | null;
  street?: string | null;
  postalCode?: string | null;
  city?: string | null;
  // Organisation (analog Microsoft 365 /me)
  jobTitle?: string | null;
  department?: string | null;
  companyName?: string | null;
  officeLocation?: string | null;
  role: string;
  twoFactorEnabled: boolean;
}

interface AuthContextType {
  user: User | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  login: (email: string, password: string, totpCode?: string) => Promise<LoginResult>;
  loginWithToken: (accessToken: string) => Promise<void>;
  logout: () => Promise<void>;
  refreshUser: () => Promise<void>;
}

interface LoginResult {
  success: boolean;
  requiresTwoFactor?: boolean;
  error?: string;
}

const AuthContext = createContext<AuthContextType | null>(null);

export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<User | null>(null);
  const [isLoading, setIsLoading] = useState(true);

  // Beim Start: Silent Refresh versuchen
  useEffect(() => {
    const initAuth = async () => {
      try {
        const { data } = await api.post<{ accessToken: string }>(
          '/auth/refresh',
        );
        setAccessToken(data.accessToken);

        // User-Profil laden
        const profileResponse = await api.get<User>('/users/me');
        setUser(profileResponse.data);
      } catch {
        // Nicht eingeloggt - normal
        setAccessToken(null);
        setUser(null);
      } finally {
        setIsLoading(false);
      }
    };

    initAuth();
  }, []);

  const login = useCallback(
    async (
      email: string,
      password: string,
      totpCode?: string,
    ): Promise<LoginResult> => {
      try {
        const { data } = await api.post<{
          accessToken?: string;
          user?: User;
          requiresTwoFactor?: boolean;
        }>('/auth/login', { email, password, totpCode });

        if (data.requiresTwoFactor) {
          return { success: false, requiresTwoFactor: true };
        }

        if (data.accessToken && data.user) {
          setAccessToken(data.accessToken);
          setUser(data.user);
          return { success: true };
        }

        return { success: false, error: 'Unerwartete Antwort vom Server' };
      } catch (err: unknown) {
        const error = err as { response?: { data?: { message?: string } } };
        return {
          success: false,
          error: error.response?.data?.message ?? 'Login fehlgeschlagen',
        };
      }
    },
    [],
  );

  /**
   * SSO-Login: Access-Token direkt setzen und User-Profil laden.
   * Wird von SsoCallbackPage aufgerufen.
   */
  const loginWithToken = useCallback(async (token: string) => {
    setAccessToken(token);
    const { data } = await api.get<User>('/users/me');
    setUser(data);
  }, []);

  const refreshUser = useCallback(async () => {
    try {
      const { data } = await api.get<User>('/users/me');
      setUser(data);
    } catch {
      // Fehler ignorieren - User bleibt unverändert
    }
  }, []);

  const logout = useCallback(async () => {
    try {
      await api.post('/auth/logout');
    } catch {
      // Fehler ignorieren
    } finally {
      setAccessToken(null);
      setUser(null);
    }
  }, []);

  return (
    <AuthContext.Provider
      value={{
        user,
        isAuthenticated: !!user,
        isLoading,
        login,
        loginWithToken,
        logout,
        refreshUser,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
}

export function useAuth(): AuthContextType {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuth muss innerhalb von AuthProvider verwendet werden');
  }
  return context;
}
