import { jwtDecode } from "jwt-decode";
import { TokenManager } from "../token-manager/token-manager";

interface Identifier {
  type: string;
  value: string;
}

interface JWTPayload {
  access_info?: {
    role_type?: string;
    trace_user_given_name?: string;
    trace_user_family_name?: string;
    module_code?: string;
    identifier?: Identifier[];
  };
}

export interface UserManager {
  getRole: () => string | undefined;
  isUserRoleAdministrative: () => boolean;
  getFullName: () => string | undefined;
  getSector: () => string | undefined;
  getDNI: () => string | undefined;
}

export class UserManagerImpl implements UserManager {
  constructor(private tokenManager: TokenManager) {}

  private getAccessInfo(): JWTPayload["access_info"] | undefined {
    const token = this.tokenManager.getToken();
    if (!token) return undefined;
    try {
      return jwtDecode<JWTPayload>(token).access_info;
    } catch (error) {
      console.error("Error decoding JWT token:", error);
      return undefined;
    }
  }

  getRole = (): string | undefined => {
    return this.getAccessInfo()?.role_type;
  };

  isUserRoleAdministrative = (): boolean => {
    return this.getRole() === "ADM";
  };

  getFullName = (): string | undefined => {
    const accessInfo = this.getAccessInfo();
    if (!accessInfo) return undefined;

    const givenName = accessInfo.trace_user_given_name;
    const familyName = accessInfo.trace_user_family_name;

    if (!givenName && !familyName) return undefined;

    return [familyName, givenName].filter(Boolean).join(" ");
  };

  getSector = (): string | undefined => {
    return this.getAccessInfo()?.module_code;
  };

  getDNI = (): string | undefined => {
    const identifiers = this.getAccessInfo()?.identifier;
    if (!identifiers) return undefined;

    const dniIdentifier = identifiers.find(id => id.type === "DNI");
    return dniIdentifier?.value;
  };
}

let userManager: UserManager;
export const createUserManager = (tokenManager: TokenManager): UserManager => {
  if (userManager) return userManager;
  userManager = new UserManagerImpl(tokenManager);
  return userManager;
};
