import React, { createContext, useContext, useState, useEffect } from "react";
import toast from "react-hot-toast";
import apiService from "~/lib/api";

interface User {
  id: number;
  name: string;
  family: string;
  email: string;
  username: string;
  mobile?: string;
  nationalCode?: string;
  status: boolean;
  customTheme?: string;
}

interface Token {
  id: number;
  accessToken: string;
  expAccessTokenStamp: string;
  expAccessToken: string;
  refreshToken: string;
  expRefreshToken: string;
  expRefreshTokenStamp: string;
}

interface AuthContextType {
  user: User | null;
  token: Token | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  login: (username: string, password: string) => Promise<boolean>;
  logout: () => void;
  validateToken: () => Promise<boolean>;
}

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

interface AuthProviderProps {
  children: React.ReactNode;
}

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

  // Token validation function
  const validateToken = async (tokenToValidate?: Token): Promise<boolean> => {
    const currentToken = tokenToValidate || token;

    if (!currentToken || !currentToken.accessToken) {
      return false;
    }

    try {
      // Check if token is expired using the expAccessTokenStamp
      const expirationDate = new Date(currentToken.expAccessTokenStamp);
      const currentDate = new Date();

      if (expirationDate <= currentDate) {
        // Token is expired
        clearAuthData();
        return false;
      }

      return true;
    } catch (error) {
      console.error("Token validation error:", error);
      return false;
    }
  };

  const clearAuthData = () => {
    setUser(null);
    setToken(null);
    localStorage.removeItem("auth_user");
    localStorage.removeItem("auth_token");
  };

  useEffect(() => {
    const initAuth = async () => {
      try {
        // Check for existing user and token in localStorage on mount
        const savedUser = localStorage.getItem("auth_user");
        const savedToken = localStorage.getItem("auth_token");

        if (savedUser && savedToken) {
          try {
            const userData = JSON.parse(savedUser);
            const tokenData = JSON.parse(savedToken);

            // Validate the saved token
            const isValidToken = await validateToken(tokenData);

            if (isValidToken) {
              setUser(userData);
              setToken(tokenData);
            } else {
              // Token is invalid, clear auth data
              clearAuthData();
            }
          } catch (error) {
            console.error("Error parsing saved user data:", error);
            clearAuthData();
          }
        }
      } catch (error) {
        console.error("Auth initialization error:", error);
        clearAuthData();
      } finally {
        setIsLoading(false);
      }
    };

    initAuth();
  }, []);

  // Auto-validate token every 5 minutes
  useEffect(() => {
    if (!token || !user) return;

    const interval = setInterval(
      async () => {
        const isValid = await validateToken();
        if (!isValid) {
          clearAuthData();
        }
      },
      5 * 60 * 1000,
    ); // 5 minutes

    return () => clearInterval(interval);
  }, [token, user]);

  const login = async (
    username: string,
    password: string,
  ): Promise<boolean> => {
    if (!username || !password) {
      toast.error("لطفاً تمام فیلدها را پر کنید");
      return false;
    }

    setIsLoading(true);

    try {
      const result = await apiService.login(username, password);

      if (result.success && result.data) {
        const tokenData: Token = {
          id: result.data.Token.ID,
          accessToken: result.data.Token.AccessToken,
          expAccessTokenStamp: result.data.Token.ExpAccessTokenStamp,
          expAccessToken: result.data.Token.ExpAccessToken,
          refreshToken: result.data.Token.RefreshToken,
          expRefreshToken: result.data.Token.ExpRefreshToken,
          expRefreshTokenStamp: result.data.Token.ExpRefreshTokenStamp,
        };

        const userData: User = {
          id: result.data.Person.ID,
          name: result.data.Person.Name,
          family: result.data.Person.Family,
          email: result.data.Person.Email,
          username: result.data.Person.Username,
          mobile: result.data.Person.Mobile,
          nationalCode: result.data.Person.NationalCode,
          status: result.data.Person.Status,
          customTheme: result.data.Person.CustomeTheme,
        };

        // Validate the received token
        const isValidToken = await validateToken(tokenData);

        if (!isValidToken) {
          toast.error("توکن دریافتی نامعتبر است");
          return false;
        }

        setUser(userData);
        setToken(tokenData);

        // Save to localStorage
        localStorage.setItem("auth_user", JSON.stringify(userData));
        localStorage.setItem("auth_token", JSON.stringify(tokenData));

        toast.success(`خوش آمدید ${userData.name} ${userData.family}!`);
        return true;
      } else {
        toast.error(result.message || "نام کاربری یا رمز عبور اشتباه است");
        return false;
      }
    } catch (error) {
      console.error("Login error:", error);
      const errorMessage =
        error instanceof Error ? error.message : "خطای غیرمنتظره رخ داد";
      toast.error(errorMessage);
      return false;
    } finally {
      setIsLoading(false);
    }
  };

  const logout = async () => {
    try {
      await apiService.logout();
    } catch (error) {
      console.error("Logout error:", error);
    } finally {
      // mark logout event to suppress next auth-required toast from guard
      try {
        sessionStorage.setItem("justLoggedOut", "1");
      } catch {}
      clearAuthData();
      toast.success("با موفقیت خارج شدید", { id: "logout-success" });
    }
  };

  const value: AuthContextType = {
    user,
    isAuthenticated: !!user && !!token,
    isLoading,
    login,
    logout,
    token,
    validateToken,
  };

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

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