import {
  MeDto,
  EPositionTypeKey,
  POSITION_TYPE_ALIASES,
} from "@/shared/dto/user/meDto";

/** Build match candidates from backend keys like performance_director or org/director */
const positionTypeCandidates = (rawKey: string): string[] => {
  const candidates = new Set<string>([rawKey]);

  const slashIdx = rawKey.lastIndexOf("/");
  if (slashIdx >= 0) {
    candidates.add(rawKey.slice(slashIdx + 1));
  }

  const underscoreIdx = rawKey.lastIndexOf("_");
  if (underscoreIdx >= 0) {
    candidates.add(rawKey.slice(underscoreIdx + 1));
  }

  if (rawKey.toLowerCase().startsWith("performance_")) {
    candidates.add(rawKey.slice("performance_".length));
  }

  // performance_teamleader → teamleader → team-leader
  if (rawKey.toLowerCase().includes("teamleader")) {
    candidates.add("teamleader");
    candidates.add("team-leader");
  }

  return [...candidates];
};

/**
 * Returns true when a backend key matches the canonical position type.
 * Checks positionType.key (e.g. performance_director) and position.key (e.g. org/director).
 */
export const matchesPositionType = (
  rawKey: string | undefined | null,
  level: EPositionTypeKey,
): boolean => {
  if (!rawKey) return false;
  const aliases = POSITION_TYPE_ALIASES[level] ?? [level];
  return positionTypeCandidates(rawKey).some((candidate) => aliases.includes(candidate));
};

/** Resolve positionType.key or position.key to canonical EPositionTypeKey. */
export const resolvePositionTypeKey = (
  rawKey: string | undefined | null,
): EPositionTypeKey | null => {
  if (!rawKey) return null;
  for (const level of Object.values(EPositionTypeKey)) {
    if (matchesPositionType(rawKey, level as EPositionTypeKey)) {
      return level as EPositionTypeKey;
    }
  }
  return null;
};

type PositionLike = {
  key?: string;
  positionType?: { key?: string } | null;
};

export const resolvePositionType = (
  position: PositionLike | undefined | null,
): EPositionTypeKey | null => {
  if (!position) return null;
  return (
    resolvePositionTypeKey(position.positionType?.key) ??
    resolvePositionTypeKey(position.key) ??
    null
  );
};

/**
 * Get user's highest position type based on hierarchy priority
 * Priority order: DEPUTY > DIRECTOR > BUDGET_PLAN > OFFICE_HEAD > TEAM_LEADER > EMPLOYEE
 */
export const getUserPositionType = (
  user: MeDto | null,
): EPositionTypeKey | null => {
  if (!user?.employee?.length) return null;

  const positions = user.employee[0]?.positions || [];
  if (!positions.length) return null;

  const positionHierarchy = [
    EPositionTypeKey.DEPUTY,
    EPositionTypeKey.DIRECTOR,
    EPositionTypeKey.BUDGET_PLAN,
    EPositionTypeKey.OFFICE_HEAD,
    EPositionTypeKey.TEAM_LEADER,
    EPositionTypeKey.EMPLOYEE,
  ];

  for (const level of positionHierarchy) {
    const hasPosition = positions.some((p) => resolvePositionType(p) === level);
    if (hasPosition) return level;
  }

  return EPositionTypeKey.EMPLOYEE;
};

/**
 * Position type for the currently selected position (employeePositionId or position id).
 */
export const getSelectedPositionType = (
  user: MeDto | null,
  selectedPositionId: string | null | undefined,
): EPositionTypeKey | null => {
  if (!user?.employee?.length) return null;

  const allPositions = user.employee.flatMap((emp) => emp.positions ?? []);

  if (selectedPositionId) {
    const active = allPositions.find(
      (p) =>
        p.employeePositionId === selectedPositionId || p.id === selectedPositionId,
    );
    const resolved = resolvePositionType(active);
    if (resolved) return resolved;
  }

  return getUserPositionType(user);
};

export const hasPositionType = (
  user: MeDto | null,
  type: EPositionTypeKey,
): boolean => {
  if (!user?.employee?.length) return false;
  const positions = user.employee[0]?.positions || [];
  return positions.some((p) => resolvePositionType(p) === type);
};

export const getUserOrgContext = (user: MeDto | null) => {
  if (!user?.employee?.length) return null;

  const employee = user.employee[0];
  const position = employee?.positions?.[0];

  return {
    organizationId: employee?.organizationId,
    unitId: employee?.unitId,
    employeeId: employee?.id,
    positionId: position?.id,
  };
};

export const getUserPositionId = (user: MeDto | null): string | null => {
  if (!user?.employee?.length) return null;
  return user.employee[0]?.positions?.[0]?.id || null;
};
