import { useState, useEffect, useCallback, useRef } from "react";
import { useRouter } from "next/navigation";
import { apiCall } from "@/lib/api/client";
import { AuthLogger } from "@/lib/authLogger";

interface UserInfo {
  userId: string;
  userName: string;
  userNameEng?: string;
  userNameCn?: string;
  deptCode?: string;
  deptName?: string;
  positionCode?: string;
  positionName?: string;
  email?: string;
  tel?: string;
  cellPhone?: string;
  userType?: string;
  userTypeName?: string;
  authName?: string;
  partnerCd?: string;
  locale?: string;
  isAdmin: boolean;
  sabun?: string;
  photo?: string | null;
  companyCode?: string;
  company_code?: string;
}

interface AuthStatus {
  isLoggedIn: boolean;
  isAdmin: boolean;
  userId?: string;
  deptCode?: string;
}

interface LoginResult {
  success: boolean;
  message: string;
  errorCode?: string;
}

interface ApiResponse<T = any> {
  success: boolean;
  message: string;
  data?: T;
  errorCode?: string;
}

// JWT 토큰 관리 유틸리티 (client.ts와 동일한 localStorage 키 사용)
const TokenManager = {
  getToken: (): string | null => {
    if (typeof window !== "undefined") {
      return localStorage.getItem("authToken");
    }
    return null;
  },

  setToken: (token: string): void => {
    if (typeof window !== "undefined") {
      localStorage.setItem("authToken", token);
      // 쿠키에도 저장 (미들웨어에서 사용)
      document.cookie = `authToken=${token}; path=/; max-age=86400; SameSite=Lax`;
    }
  },

  removeToken: (): void => {
    if (typeof window !== "undefined") {
      localStorage.removeItem("authToken");
      document.cookie = "authToken=; path=/; max-age=0; SameSite=Lax";
    }
  },

  isTokenExpired: (token: string): boolean => {
    try {
      const payload = JSON.parse(atob(token.split(".")[1]));
      return payload.exp * 1000 < Date.now();
    } catch {
      return true;
    }
  },
};

/**
 * 인증 상태 관리 훅
 * - 401 처리는 client.ts의 응답 인터셉터에서 통합 관리
 * - 이 훅은 상태 관리와 사용자 정보 조회에만 집중
 */
export const useAuth = () => {
  const router = useRouter();

  const [user, setUser] = useState<UserInfo | null>(null);
  const [authStatus, setAuthStatus] = useState<AuthStatus>({
    isLoggedIn: false,
    isAdmin: false,
  });
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const initializedRef = useRef(false);

  /**
   * 현재 사용자 정보 조회
   */
  const fetchCurrentUser = useCallback(async (): Promise<UserInfo | null> => {
    try {
      const response = await apiCall<UserInfo>("GET", "/auth/me");

      if (response.success && response.data) {
        // 사용자 로케일 정보 조회
        try {
          const localeResponse = await apiCall<string>("GET", "/admin/user-locale");
          if (localeResponse.success && localeResponse.data) {
            const userLocale = localeResponse.data;
            (window as any).__GLOBAL_USER_LANG = userLocale;
            (window as any).__GLOBAL_USER_LOCALE_LOADED = true;
            localStorage.setItem("userLocale", userLocale);
            localStorage.setItem("userLocaleLoaded", "true");
          }
        } catch {
          (window as any).__GLOBAL_USER_LANG = "KR";
          (window as any).__GLOBAL_USER_LOCALE_LOADED = true;
          localStorage.setItem("userLocale", "KR");
          localStorage.setItem("userLocaleLoaded", "true");
        }

        return response.data;
      }

      return null;
    } catch {
      return null;
    }
  }, []);

  /**
   * 인증 상태 확인
   */
  const checkAuthStatus = useCallback(async (): Promise<AuthStatus> => {
    try {
      const response = await apiCall<AuthStatus>("GET", "/auth/status");
      if (response.success && response.data) {
        return {
          isLoggedIn: (response.data as any).isAuthenticated || response.data.isLoggedIn || false,
          isAdmin: response.data.isAdmin || false,
        };
      }

      return { isLoggedIn: false, isAdmin: false };
    } catch {
      return { isLoggedIn: false, isAdmin: false };
    }
  }, []);

  /**
   * 사용자 데이터 새로고침
   * - API 실패 시에도 토큰이 유효하면 토큰 기반으로 임시 인증 유지
   * - 토큰 자체가 없거나 만료된 경우에만 비인증 상태로 전환
   */
  const refreshUserData = useCallback(async () => {
    try {
      setLoading(true);

      const token = TokenManager.getToken();
      if (!token) {
        AuthLogger.log("AUTH_CHECK_FAIL", "refreshUserData: 토큰 없음");
        setUser(null);
        setAuthStatus({ isLoggedIn: false, isAdmin: false });
        setLoading(false);
        return;
      }
      // 만료된 토큰이라도 apiClient 요청 인터셉터가 자동 갱신하므로 여기서 차단하지 않음

      AuthLogger.log("AUTH_CHECK_START", "refreshUserData: API로 인증 상태 확인 시작");

      setAuthStatus({
        isLoggedIn: true,
        isAdmin: false,
      });

      try {
        // /auth/me 성공 = 인증 확인 완료. /auth/status는 보조 정보(isAdmin)만 참조
        // 두 API를 Promise.all로 호출 시, 토큰 만료 타이밍에 따라
        // /auth/me는 401→갱신→성공, /auth/status는 200 isAuthenticated:false를 반환하는
        // 레이스 컨디션이 발생할 수 있으므로, isLoggedIn 판단은 /auth/me 성공 여부로 결정
        const [userInfo, authStatusData] = await Promise.all([fetchCurrentUser(), checkAuthStatus()]);

        if (userInfo) {
          setUser(userInfo);

          const isAdminFromUser = userInfo.userId === "plm_admin" || userInfo.userType === "ADMIN";
          const finalAuthStatus = {
            isLoggedIn: true,
            isAdmin: authStatusData.isAdmin || isAdminFromUser,
          };

          setAuthStatus(finalAuthStatus);
          AuthLogger.log("AUTH_CHECK_SUCCESS", `사용자: ${userInfo.userId}, 인증: ${finalAuthStatus.isLoggedIn}`);
        } else {
          AuthLogger.log("AUTH_CHECK_FAIL", "userInfo 조회 실패 → 토큰 기반 임시 인증 유지 시도");
          try {
            const payload = JSON.parse(atob(token.split(".")[1]));
            const tempUser: UserInfo = {
              userId: payload.userId || payload.id || "unknown",
              userName: payload.userName || payload.name || "사용자",
              companyCode: payload.companyCode || payload.company_code || "",
              isAdmin: payload.userId === "plm_admin" || payload.userType === "ADMIN",
            };

            setUser(tempUser);
            setAuthStatus({
              isLoggedIn: true,
              isAdmin: tempUser.isAdmin,
            });
          } catch {
            AuthLogger.log("AUTH_CHECK_FAIL", "토큰 파싱 실패 → 비인증 전환");
            TokenManager.removeToken();
            setUser(null);
            setAuthStatus({ isLoggedIn: false, isAdmin: false });
          }
        }
      } catch {
        AuthLogger.log("AUTH_CHECK_FAIL", "API 호출 전체 실패 → 토큰 기반 임시 인증 유지 시도");
        try {
          const payload = JSON.parse(atob(token.split(".")[1]));
          const tempUser: UserInfo = {
            userId: payload.userId || payload.id || "unknown",
            userName: payload.userName || payload.name || "사용자",
            companyCode: payload.companyCode || payload.company_code || "",
            isAdmin: payload.userId === "plm_admin" || payload.userType === "ADMIN",
          };

          setUser(tempUser);
          setAuthStatus({
            isLoggedIn: true,
            isAdmin: tempUser.isAdmin,
          });
        } catch {
          AuthLogger.log("AUTH_CHECK_FAIL", "최종 fallback 실패 → 비인증 전환");
          TokenManager.removeToken();
          setUser(null);
          setAuthStatus({ isLoggedIn: false, isAdmin: false });
        }
      }
    } catch {
      setError("사용자 정보를 불러오는데 실패했습니다.");
      setUser(null);
      setAuthStatus({ isLoggedIn: false, isAdmin: false });
    } finally {
      setLoading(false);
    }
  }, [fetchCurrentUser, checkAuthStatus]);

  /**
   * 로그인 처리
   */
  const login = useCallback(
    async (userId: string, password: string): Promise<LoginResult> => {
      try {
        setLoading(true);
        setError(null);

        const response = await apiCall<any>("POST", "/auth/login", {
          userId,
          password,
        });

        if (response.success && response.data?.token) {
          TokenManager.setToken(response.data.token);
          await refreshUserData();

          return {
            success: true,
            message: response.message || "로그인에 성공했습니다.",
          };
        } else {
          return {
            success: false,
            message: response.message || "로그인에 실패했습니다.",
            errorCode: response.errorCode,
          };
        }
      } catch (error: any) {
        const errorMessage = error.message || "로그인 중 오류가 발생했습니다.";
        setError(errorMessage);

        return {
          success: false,
          message: errorMessage,
        };
      } finally {
        setLoading(false);
      }
    },
    [refreshUserData],
  );

  /**
   * 회사 전환 처리 (WACE 관리자 전용)
   */
  const switchCompany = useCallback(
    async (companyCode: string): Promise<{ success: boolean; message: string }> => {
      try {
        setLoading(true);
        setError(null);

        const response = await apiCall<any>("POST", "/auth/switch-company", {
          companyCode,
        });

        if (response.success && response.data?.token) {
          TokenManager.setToken(response.data.token);

          return {
            success: true,
            message: response.message || "회사 전환에 성공했습니다.",
          };
        } else {
          return {
            success: false,
            message: response.message || "회사 전환에 실패했습니다.",
          };
        }
      } catch (error: any) {
        const errorMessage = error.message || "회사 전환 중 오류가 발생했습니다.";
        setError(errorMessage);

        return {
          success: false,
          message: errorMessage,
        };
      } finally {
        setLoading(false);
      }
    },
    [],
  );

  /**
   * 로그아웃 처리
   */
  const logout = useCallback(async (): Promise<boolean> => {
    try {
      setLoading(true);

      const response = await apiCall("POST", "/auth/logout");

      TokenManager.removeToken();

      localStorage.removeItem("userLocale");
      localStorage.removeItem("userLocaleLoaded");
      (window as any).__GLOBAL_USER_LANG = undefined;
      (window as any).__GLOBAL_USER_LOCALE_LOADED = undefined;

      setUser(null);
      setAuthStatus({ isLoggedIn: false, isAdmin: false });
      setError(null);

      router.push("/login");

      return response.success;
    } catch {
      TokenManager.removeToken();

      localStorage.removeItem("userLocale");
      localStorage.removeItem("userLocaleLoaded");
      (window as any).__GLOBAL_USER_LANG = undefined;
      (window as any).__GLOBAL_USER_LOCALE_LOADED = undefined;

      setUser(null);
      setAuthStatus({ isLoggedIn: false, isAdmin: false });
      router.push("/login");

      return false;
    } finally {
      setLoading(false);
    }
  }, [router]);

  /**
   * 메뉴 접근 권한 확인
   */
  const checkMenuAuth = useCallback(async (menuUrl: string): Promise<boolean> => {
    try {
      const response = await apiCall<{ menuUrl: string; hasAuth: boolean }>("GET", "/auth/menu-auth");

      if (response.success && response.data) {
        return response.data.hasAuth;
      }

      return false;
    } catch {
      return false;
    }
  }, []);

  /**
   * 초기 인증 상태 확인
   */
  useEffect(() => {
    if (initializedRef.current) return;
    initializedRef.current = true;

    if (typeof window === "undefined") return;

    // 로그인 페이지에서는 인증 상태 확인하지 않음
    if (window.location.pathname === "/login") {
      setLoading(false);
      return;
    }

    const token = TokenManager.getToken();

    if (token) {
      // 유효/만료 모두 refreshUserData로 처리
      // apiClient 요청 인터셉터가 만료 토큰을 자동 갱신하므로 여기서 삭제하지 않음
      const isExpired = TokenManager.isTokenExpired(token);
      AuthLogger.log(
        "AUTH_CHECK_START",
        `초기 인증 확인: 토큰 ${isExpired ? "만료됨 → 갱신 시도" : "유효"} (경로: ${window.location.pathname})`,
      );
      setAuthStatus({
        isLoggedIn: true,
        isAdmin: false,
      });
      refreshUserData();
    } else {
      AuthLogger.log("AUTH_CHECK_FAIL", `초기 확인: 토큰 없음 (경로: ${window.location.pathname})`);
      setAuthStatus({ isLoggedIn: false, isAdmin: false });
      setLoading(false);
    }
  }, []);

  return {
    user,
    authStatus,
    loading,
    error,

    isLoggedIn: authStatus.isLoggedIn,
    isAdmin: authStatus.isAdmin,
    userId: user?.userId,
    userName: user?.userName,
    companyCode: user?.companyCode || user?.company_code,

    login,
    logout,
    switchCompany,
    checkMenuAuth,
    refreshUserData,

    clearError: () => setError(null),
  };
};

export default useAuth;
