import { createContext, useCallback, useContext, useMemo, useState } from 'react';

import { apiClient } from '../../api/apiClient';
import { authStore } from './authStore';
import { loadAuthFromStorage, saveAuthToStorage } from './storage';

type AuthContextValue = {
  token: string | null;
  username: string | null;
  isHydrating: boolean;
  hydrate: () => Promise<void>;
  login: (email: string, password: string) => Promise<void>;
  logout: () => Promise<void>;
};

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

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [token, setToken] = useState<string | null>(null);
  const [username, setUsername] = useState<string | null>(null);
  const [isHydrating, setIsHydrating] = useState(true);

  const hydrate = useCallback(async () => {
    setIsHydrating(true);
    try {
      const stored = await loadAuthFromStorage();
      setToken(stored.token);
      setUsername(stored.username);
      authStore.setToken(stored.token);
      authStore.setUsername(stored.username);
    } finally {
      setIsHydrating(false);
    }
  }, []);

  const login = useCallback(async (email: string, password: string) => {
    const response = await apiClient.post('/auth/login', { email, password });
    if (response.status !== 200 || !response.data?.token) {
      throw new Error(response.data?.error || 'Login fehlgeschlagen');
    }

    const newToken = String(response.data.token);
    setToken(newToken);
    setUsername(email);
    authStore.setToken(newToken);
    authStore.setUsername(email);
    await saveAuthToStorage(newToken, email);
  }, []);

  const logout = useCallback(async () => {
    const currentToken = authStore.getToken();
    try {
      if (currentToken) {
        await apiClient.post(
          '/auth/logout',
          {},
          { headers: { Authorization: `Bearer ${currentToken}` } }
        );
      }
    } finally {
      setToken(null);
      setUsername(null);
      authStore.setToken(null);
      authStore.setUsername(null);
      await saveAuthToStorage(null, null);
    }
  }, []);

  const value = useMemo<AuthContextValue>(
    () => ({ token, username, isHydrating, hydrate, login, logout }),
    [token, username, isHydrating, hydrate, login, logout]
  );

  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}

export function useAuth() {
  const value = useContext(AuthContext);
  if (!value) {
    throw new Error('useAuth must be used within AuthProvider');
  }
  return value;
}

