import { useCallback, useEffect, useMemo, useState, type ReactNode } from 'react';
import type { AuthResponse, User } from './types';
import { authApi } from './authApi';
import { AuthContext } from './AuthContext';

const DEV_MOCK_USER: User = {
  id: 1,
  email: 'htlee@gcsc.co.kr',
  name: '김개발 (DEV)',
  avatarUrl: null,
  status: 'ACTIVE',
  isAdmin: true,
  roles: [
    { id: 1, name: 'ADMIN', description: '관리자', urlPatterns: ['/**'] },
    { id: 99, name: 'WING_PERMIT', description: 'Wing 접근 권한', urlPatterns: [] },
  ],
  createdAt: new Date().toISOString(),
  lastLoginAt: new Date().toISOString(),
};

function isDevMockSession(): boolean {
  return import.meta.env.DEV && localStorage.getItem('dev-user') === 'true';
}

export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<User | null>(() =>
    isDevMockSession() ? DEV_MOCK_USER : null,
  );
  const [token, setToken] = useState<string | null>(
    () => localStorage.getItem('token'),
  );
  const [initialized, setInitialized] = useState(
    () => isDevMockSession() || !localStorage.getItem('token'),
  );

  const logout = useCallback(() => {
    const hadToken = !!localStorage.getItem('token') && !isDevMockSession();
    localStorage.removeItem('token');
    localStorage.removeItem('dev-user');
    setToken(null);
    setUser(null);
    if (hadToken) {
      authApi.post('/auth/logout').catch(() => {});
    }
  }, []);

  const devLogin = useCallback(() => {
    localStorage.setItem('dev-user', 'true');
    localStorage.setItem('token', 'dev-mock-token');
    setToken('dev-mock-token');
    setUser(DEV_MOCK_USER);
    setInitialized(true);
  }, []);

  const login = useCallback(async (googleToken: string) => {
    const res = await authApi.post<AuthResponse>('/auth/google', {
      idToken: googleToken,
    });
    localStorage.setItem('token', res.token);
    setToken(res.token);
    setUser(res.user);
  }, []);

  useEffect(() => {
    if (!token || isDevMockSession()) return;

    let cancelled = false;
    authApi
      .get<User>('/auth/me')
      .then((data) => {
        if (!cancelled) setUser(data);
      })
      .catch(() => {
        if (!cancelled) logout();
      })
      .finally(() => {
        if (!cancelled) setInitialized(true);
      });
    return () => {
      cancelled = true;
    };
  }, [token, logout]);

  const loading = !initialized;

  const value = useMemo(
    () => ({
      user,
      token,
      loading,
      login,
      devLogin: import.meta.env.DEV ? devLogin : undefined,
      logout,
    }),
    [user, token, loading, login, devLogin, logout],
  );

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