"use client";

import React, { createContext, useContext, useState, useEffect, useCallback } from "react";
import { AppUserRecord } from "@/lib/userManagementTypes";
import { getRoleRedirectPath } from "@/lib/authTypes";

interface AuthContextType {
  user: AppUserRecord | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  isImpersonating: boolean;
  originalAdmin: AppUserRecord | null;
  login: (
    identifier: string,
    password: string,
    rememberMe?: boolean
  ) => Promise<{ success: boolean; redirectUrl?: string; message?: string }>;
  logout: () => Promise<void>;
  refreshUser: () => Promise<void>;
  impersonateUser: (userId: number) => Promise<{ success: boolean; redirectUrl?: string; message?: string }>;
  stopImpersonating: () => Promise<void>;
}

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

const LOCAL_STORAGE_KEY = "bpi_current_user";
const LOCAL_STORAGE_ORIGINAL_ADMIN_KEY = "bpi_original_admin";

export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [user, setUser] = useState<AppUserRecord | null>(null);
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [isImpersonating, setIsImpersonating] = useState<boolean>(false);
  const [originalAdmin, setOriginalAdmin] = useState<AppUserRecord | null>(null);

  // Periksa sesi aktif saat inisialisasi awal
  const refreshUser = useCallback(async () => {
    try {
      // 1. Coba baca dari localStorage dulu untuk respons instan
      if (typeof window !== "undefined") {
        const cached = localStorage.getItem(LOCAL_STORAGE_KEY);
        const cachedAdmin = localStorage.getItem(LOCAL_STORAGE_ORIGINAL_ADMIN_KEY);
        if (cached) {
          try {
            setUser(JSON.parse(cached));
          } catch {
            localStorage.removeItem(LOCAL_STORAGE_KEY);
          }
        }
        if (cachedAdmin) {
          try {
            setOriginalAdmin(JSON.parse(cachedAdmin));
            setIsImpersonating(true);
          } catch {
            localStorage.removeItem(LOCAL_STORAGE_ORIGINAL_ADMIN_KEY);
          }
        }
      }

      // 2. Verifikasi dengan server via /api/auth/me
      const res = await fetch("/api/auth/me", { cache: "no-store" });
      const json = await res.json();

      if (json.success && json.authenticated && json.user) {
        setUser(json.user);
        setIsImpersonating(Boolean(json.isImpersonating));
        setOriginalAdmin(json.originalAdmin || null);

        if (typeof window !== "undefined") {
          localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(json.user));
          if (json.isImpersonating && json.originalAdmin) {
            localStorage.setItem(LOCAL_STORAGE_ORIGINAL_ADMIN_KEY, JSON.stringify(json.originalAdmin));
          } else {
            localStorage.removeItem(LOCAL_STORAGE_ORIGINAL_ADMIN_KEY);
          }
        }
      } else {
        setUser(null);
        setIsImpersonating(false);
        setOriginalAdmin(null);
        if (typeof window !== "undefined") {
          localStorage.removeItem(LOCAL_STORAGE_KEY);
          localStorage.removeItem(LOCAL_STORAGE_ORIGINAL_ADMIN_KEY);
        }
      }
    } catch (err) {
      console.warn("Gagal memverifikasi sesi pengguna:", err);
    } finally {
      setIsLoading(false);
    }
  }, []);

  useEffect(() => {
    refreshUser();
  }, [refreshUser]);

  // Fungsi Login
  const login = useCallback(
    async (identifier: string, password: string, rememberMe = true) => {
      try {
        const res = await fetch("/api/auth/login", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ identifier, password, rememberMe }),
        });

        const rawText = await res.text();
        let json: any = null;
        try {
          json = JSON.parse(rawText);
        } catch (parseErr) {
          console.error("Gagal parse respon JSON login:", parseErr, "status:", res.status, "body:", rawText);
          return {
            success: false,
            message: `Gagal masuk (HTTP ${res.status}): ${rawText ? rawText.replace(/<[^>]*>/g, '').trim().slice(0, 150) : "Respon server kosong atau tidak valid."}`,
          };
        }

        if (res.ok && json.success && json.user) {
          setUser(json.user);
          setIsImpersonating(false);
          setOriginalAdmin(null);

          if (typeof window !== "undefined") {
            localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(json.user));
            localStorage.removeItem(LOCAL_STORAGE_ORIGINAL_ADMIN_KEY);
          }
          return {
            success: true,
            redirectUrl: json.redirectUrl || getRoleRedirectPath(json.user.role),
            message: json.message,
          };
        } else {
          return {
            success: false,
            message: json.message || "Gagal masuk ke aplikasi. Silakan periksa kembali akun Anda.",
          };
        }
      } catch (err: any) {
        console.error("Error login client:", err);
        return {
          success: false,
          message: err?.message ? `Gangguan jaringan/server: ${err.message}` : "Terjadi gangguan koneksi jaringan saat mencoba login.",
        };
      }
    },
    []
  );

  // Fungsi Impersonate User (Khusus Super Admin)
  const impersonateUser = useCallback(async (userId: number) => {
    try {
      const res = await fetch("/api/auth/impersonate", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ userId }),
      });

      const json = await res.json();

      if (res.ok && json.success && json.user) {
        setUser(json.user);
        setIsImpersonating(true);
        setOriginalAdmin(json.originalAdmin || null);

        if (typeof window !== "undefined") {
          localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(json.user));
          if (json.originalAdmin) {
            localStorage.setItem(LOCAL_STORAGE_ORIGINAL_ADMIN_KEY, JSON.stringify(json.originalAdmin));
          }
          // Redirect instan ke dashboard yang sesuai dengan role akun target
          window.location.href = json.redirectUrl || getRoleRedirectPath(json.user.role);
        }
        return {
          success: true,
          redirectUrl: json.redirectUrl,
          message: json.message,
        };
      } else {
        return {
          success: false,
          message: json.message || "Gagal beralih ke pengguna yang dipilih.",
        };
      }
    } catch (err: any) {
      console.error("Error impersonate client:", err);
      return {
        success: false,
        message: "Terjadi kesalahan jaringan saat mencoba beralih akun.",
      };
    }
  }, []);

  // Fungsi Berhenti Impersonate / Kembali ke Super Admin
  const stopImpersonating = useCallback(async () => {
    try {
      const res = await fetch("/api/auth/impersonate/exit", {
        method: "POST",
      });

      const json = await res.json();

      if (res.ok && json.success && json.user) {
        setUser(json.user);
        setIsImpersonating(false);
        setOriginalAdmin(null);

        if (typeof window !== "undefined") {
          localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(json.user));
          localStorage.removeItem(LOCAL_STORAGE_ORIGINAL_ADMIN_KEY);
          window.location.href = json.redirectUrl || "/user-manajemen";
        }
      } else {
        if (typeof window !== "undefined") {
          window.location.href = "/user-manajemen";
        }
      }
    } catch (err) {
      console.error("Error stopping impersonation:", err);
      if (typeof window !== "undefined") {
        window.location.href = "/user-manajemen";
      }
    }
  }, []);

  // Fungsi Logout
  const logout = useCallback(async () => {
    try {
      await fetch("/api/auth/logout", { method: "POST" });
    } catch (err) {
      console.warn("Error calling logout API:", err);
    } finally {
      setUser(null);
      setIsImpersonating(false);
      setOriginalAdmin(null);
      if (typeof window !== "undefined") {
        localStorage.removeItem(LOCAL_STORAGE_KEY);
        localStorage.removeItem(LOCAL_STORAGE_ORIGINAL_ADMIN_KEY);
        window.location.href = "/login";
      }
    }
  }, []);

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

export const useAuth = (): AuthContextType => {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error("useAuth must be used within an AuthProvider");
  }
  return context;
};
