import type { User, Role, Permission } from "@/types/auth";

import { defineStore } from "pinia";
import { ref, computed } from "vue";

import avatarImg from "@/assets/images/avatar.png";

const TOKEN_KEY = "access_token";
const USER_KEY = "user_info";

export const useAuthStore = defineStore("auth", () => {
  const token = ref<string | null>(localStorage.getItem(TOKEN_KEY));
  const user = ref<User | null>(null);
  const roles = ref<string[]>([]);
  const permissions = ref<string[]>([]);

  const isLoggedIn = computed(() => !!token.value && !!user.value);
  const userRoles = computed(() => roles.value);
  const userPermissions = computed(() => permissions.value);

  const setToken = (newToken: string | null) => {
    token.value = newToken;
    if (newToken) {
      localStorage.setItem(TOKEN_KEY, newToken);
    } else {
      localStorage.removeItem(TOKEN_KEY);
    }
  };

  const setUserInfo = (userInfo: User | null) => {
    user.value = userInfo;
    if (userInfo) {
      roles.value = ((userInfo as any).roles || []).map((r: any) => (typeof r === "string" ? r : r.code));
      permissions.value = ((userInfo as any).permissions || []).map((p: any) => (typeof p === "string" ? p : p.code));
      localStorage.setItem(USER_KEY, JSON.stringify(userInfo));
    } else {
      roles.value = [];
      permissions.value = [];
      localStorage.removeItem(USER_KEY);
    }
  };

  const login = async (user_name: string, password: string): Promise<void> => {
    const { login: loginApi } = await import("@/api/auth");
    const { getUserPermissions } = await import("@/api/permission");

    const loginResult: any = await loginApi({ user_name, password });
    const { token: newToken, user: backendUser, roles: backendRoles } = loginResult.data;
    setToken(newToken);

    let perms: string[] = [];
    // Admin role gets wildcard permission
    if ((backendRoles || []).includes("admin")) {
      perms = ["*"];
    } else {
      const permRes: any = await getUserPermissions();
      perms = permRes.data || [];
    }

    // Map backend user to frontend User format
    const mappedUser: User = {
      id: String(backendUser.id),
      username: backendUser.user_name || backendUser.username || "",
      email: backendUser.email || "",
      realName: backendUser.nick_name || backendUser.realName || backendUser.user_name || "",
      avatar: backendUser.avatar || avatarImg,
      phone: backendUser.phonenumber || backendUser.phone || "",
      gender: backendUser.gender || (backendUser.sex === "0" ? "female" : "male"),
      status: backendUser.status === "0" ? "active" : "inactive",
      deptId: backendUser.dept_id || undefined,
      createdAt: backendUser.create_time || backendUser.createdAt || "",
      updatedAt: backendUser.update_time || backendUser.updatedAt || "",
      roles: (backendRoles || []).map((code: string) => ({
        id: code,
        name: code,
        code,
        description: "",
        permissions: [],
        createdAt: "",
        updatedAt: "",
      })),
      permissions: perms.map((code: string) => ({
        id: code,
        name: code,
        code,
        description: "",
        resource: "",
        action: "",
        type: "api" as const,
      })),
    };
    setUserInfo(mappedUser);
  };

  const logout = () => {
    setToken(null);
    setUserInfo(null);
  };

  const hasRole = (role: string): boolean => {
    const raw = userRoles.value;
    const rls: string[] = raw.map((r: any) => (typeof r === "string" ? r : r.code || r.id || r));
    return rls.includes(role);
  };

  const hasAnyRole = (roleList: string[]): boolean => {
    return roleList.some((role) => hasRole(role));
  };

  const hasAllRoles = (roleList: string[]): boolean => {
    return roleList.every((role) => hasRole(role));
  };

  const hasPermission = (permission: string): boolean => {
    // Normalize permissions to string array (defense against object-array from stale localStorage)
    const raw = userPermissions.value;
    const perms: string[] = raw.map((p: any) => (typeof p === "string" ? p : p.code || p.id || p));
    return perms.includes("*") || perms.includes(permission);
  };

  const hasAnyPermission = (permissionList: string[]): boolean => {
    return permissionList.some((perm) => hasPermission(perm));
  };

  const hasAllPermissions = (permissionList: string[]): boolean => {
    return permissionList.every((perm) => hasPermission(perm));
  };

  const initAuth = () => {
    const savedToken = localStorage.getItem(TOKEN_KEY);
    if (!savedToken) {
      return;
    }

    const savedUser = localStorage.getItem(USER_KEY);
    if (savedUser) {
      try {
        const userInfo = JSON.parse(savedUser);
        setUserInfo(userInfo);
      } catch (error) {
        console.error("Failed to parse saved user info:", error);
        localStorage.removeItem(USER_KEY);
      }
    }
  };

  return {
    token,
    user,
    roles,
    permissions,
    isLoggedIn,
    userRoles,
    userPermissions,
    setToken,
    setUserInfo,
    login,
    logout,
    hasRole,
    hasAnyRole,
    hasAllRoles,
    hasPermission,
    hasAnyPermission,
    hasAllPermissions,
    initAuth,
  };
});
