import type { AuthResponse, UserResponse } from "@/api";
import type { User } from "./AuthContext";

type AuthLike = Partial<AuthResponse & UserResponse> & Record<string, unknown>;

export const DEFAULT_USER_PERMISSIONS = [
  "home:view",
  "configuration:clusters:manage_own",
  "configuration:registries:manage_own",
  "artifact:registries:view",
  "artifact:instances:manage_own",
];

const ADMIN_ROLE = "admin";

const asString = (value: unknown): string | undefined =>
  typeof value === "string" && value.trim() ? value.trim() : undefined;

const asStringArray = (value: unknown): string[] =>
  Array.isArray(value)
    ? value.filter((item): item is string => typeof item === "string" && item.trim().length > 0)
    : [];

export const normalizeUser = (source: AuthLike, fallback?: User | null): User => {
  const role = asString(source.role) ?? fallback?.role ?? "user";
  const permissions = asStringArray(source.permissions);

  return {
    userId: asString(source.userId) ?? asString(source.id) ?? fallback?.userId,
    username: asString(source.username) ?? fallback?.username ?? "",
    role,
    workspaceId: asString(source.workspaceId) ?? fallback?.workspaceId,
    workspaceName: asString(source.workspaceName) ?? fallback?.workspaceName,
    namespace: asString(source.namespace) ?? fallback?.namespace,
    defaultClusterId: asString(source.defaultClusterId) ?? fallback?.defaultClusterId,
    quotaCpu: asString(source.quotaCpu) ?? fallback?.quotaCpu,
    quotaMemory: asString(source.quotaMemory) ?? fallback?.quotaMemory,
    quotaGpu: asString(source.quotaGpu) ?? fallback?.quotaGpu,
    quotaGpuMemory: asString(source.quotaGpuMemory) ?? fallback?.quotaGpuMemory,
    permissions: permissions.length > 0 ? permissions : fallback?.permissions ?? DEFAULT_USER_PERMISSIONS,
    permissionVersion:
      typeof source.permissionVersion === "string" || typeof source.permissionVersion === "number"
        ? source.permissionVersion
        : fallback?.permissionVersion,
  };
};

export const isAdminUser = (user: User | null | undefined): boolean =>
  user?.role?.toLowerCase() === ADMIN_ROLE;

export const hasPermission = (
  user: User | null | undefined,
  permission: string,
  fallbackAllowed = true
): boolean => {
  if (!user) {
    return false;
  }
  if (isAdminUser(user)) {
    return true;
  }
  if (user.permissions.length === 0) {
    return fallbackAllowed;
  }
  return user.permissions.includes(permission) || user.permissions.includes("*");
};

export const canAccessRoute = (pathname: string, user: User | null | undefined): boolean => {
  if (!user) {
    return false;
  }

  if (pathname === "/admin" || pathname.startsWith("/admin/")) return isAdminUser(user);
  if (pathname === "/configuration/users" || pathname === "/configuration/workspaces") {
    return isAdminUser(user);
  }

  if (pathname === "/home") return hasPermission(user, "home:view");
  if (pathname === "/configuration/clusters") {
    return (
      hasPermission(user, "configuration:clusters:manage", false) ||
      hasPermission(user, "configuration:clusters:manage_own")
    );
  }
  if (pathname === "/configuration/registries") {
    return (
      hasPermission(user, "configuration:registries:manage", false) ||
      hasPermission(user, "configuration:registries:manage_own")
    );
  }
  if (pathname === "/artifact/registries") return hasPermission(user, "artifact:registries:view");
  if (pathname === "/artifact/instances") {
    return (
      hasPermission(user, "artifact:instances:manage", false) ||
      hasPermission(user, "artifact:instances:manage_own")
    );
  }
  if (pathname === "/monitoring/clusters") {
    return hasPermission(user, "monitoring:clusters:view", isAdminUser(user));
  }

  return true;
};

export type ResourceVisibility = "private" | "workspace_shared" | "global_shared" | string;

export type ResourceWithAccess = {
  visibility?: ResourceVisibility;
  ownerId?: string;
  allowedActions?: string[];
};

export const canUseResourceAction = (
  resource: ResourceWithAccess,
  action: "view" | "create" | "update" | "delete" | "test" | "launch",
  user: User | null | undefined
): boolean => {
  if (!user) {
    return false;
  }
  if (isAdminUser(user)) {
    return true;
  }
  if (Array.isArray(resource.allowedActions) && resource.allowedActions.length > 0) {
    const allowedActions = resource.allowedActions.map((allowedAction) => allowedAction.toLowerCase());
    const aliases = actionAliases[action] ?? [action];
    return allowedActions.includes("*") || aliases.some((alias) => allowedActions.includes(alias));
  }
  if (!resource.ownerId) {
    return true;
  }
  return resource.ownerId === user.userId;
};

export const getVisibilityLabel = (visibility?: ResourceVisibility): string => {
  if (visibility === "workspace_shared") return "Workspace";
  if (visibility === "global_shared") return "Global";
  if (visibility === "private") return "Private";
  return visibility ? visibility.replace(/_/g, " ") : "Private";
};

const actionAliases: Record<string, string[]> = {
  view: ["view", "read"],
  create: ["create", "add"],
  update: ["update", "edit", "manage"],
  delete: ["delete", "remove", "manage"],
  test: ["test", "health", "manage"],
  launch: ["launch", "deploy"],
};
