interface UseApplicationDetailsPermissionsParams {
  application: any;
  interviews: any[];
  currentUser: any;
  getDeposit: (type: string) => any;
  eorProgress: number;
}

function sameUserId(a: unknown, b: unknown): boolean {
  if (a == null || b == null) return false;
  return String(a).trim() === String(b).trim();
}

/** Backend / DB may use different casing (e.g. default `scheduled` vs created `Scheduled`). */
function normalizeInterviewStatus(status: unknown): string {
  return String(status ?? '')
    .trim()
    .toLowerCase()
    .replace(/\s+/g, ' ');
}

function isActiveInterviewStatus(status: unknown): boolean {
  const n = normalizeInterviewStatus(status);
  if (!n) return false;
  return (
    n === 'scheduled' ||
    n === 'rescheduled' ||
    n === 'pending' ||
    n === 'in progress' ||
    n === 'inprogress'
  );
}

function isCompletedInterviewStatus(status: unknown): boolean {
  return normalizeInterviewStatus(status) === 'completed';
}

function userIsInterviewParticipant(interview: any, userId: unknown): boolean {
  if (!userId || !interview?.participants?.length) return false;
  return interview.participants.some(
    (p: any) => sameUserId(p.userId, userId) || sameUserId(p.user?.id, userId),
  );
}

/** Which interview level the application is currently in (for feedback UI). */
function inferInterviewLevelFromApplicationStatus(status: unknown): number | undefined {
  const s = String(status ?? '').trim();
  const map: Record<string, number> = {
    'Level 1 Interview Pending': 1,
    'Level 1 Recommended': 1,
    'Level 2 Interview Pending': 2,
    'Level 2 Recommended': 2,
    'Level 3 Interview Pending': 3,
    'Level 3 Recommended': 3,
  };
  return map[s];
}

function normalizeRoleToken(value: unknown): string {
  return String(value ?? '')
    .trim()
    .toLowerCase()
    .replace(/[_\s-]+/g, '');
}

/**
 * Allow feedback when scheduling forgot to attach this user as InterviewParticipant but they are a
 * designated evaluator for this level (matches backend interview policy / schedule prefill roles).
 */
function userRoleEligibleForInterviewLevel(user: any, level: number): boolean {
  if (!user) return false;
  const privilegedRoles = ['Super Admin', 'DD Admin'];
  if (
    privilegedRoles.includes(String(user.role ?? '')) ||
    privilegedRoles.includes(String(user.roleCode ?? ''))
  ) {
    return true;
  }

  const rolesByLevel: Record<number, string[]> = {
    1: ['DD-ZM', 'DD ZM', 'RBM'],
    2: ['DD Lead', 'ZBH'],
    3: ['NBH', 'DD Head'],
  };
  const allowedRaw = rolesByLevel[level];
  if (!allowedRaw?.length) return false;

  const allowed = allowedRaw.map(normalizeRoleToken);
  const candidates = [
    user.role,
    user.roleCode,
    user.roleName,
    user.role?.roleCode,
    user.role?.roleName,
  ]
    .filter(Boolean)
    .map(normalizeRoleToken);

  for (const c of candidates) {
    if (!c) continue;
    for (const a of allowed) {
      if (!a) continue;
      if (c === a || c.includes(a) || a.includes(c)) return true;
    }
  }
  return false;
}

export function useApplicationDetailsPermissions({
  application,
  interviews,
  currentUser,
  getDeposit,
  eorProgress,
}: UseApplicationDetailsPermissionsParams) {
  const interviewsList = Array.isArray(interviews) ? interviews : [];

  const stageInterviewLevel = inferInterviewLevelFromApplicationStatus(application?.status);

  /** Prefer participant match on the interview row that matches current application stage when possible. */
  const participantActiveInterview =
    (stageInterviewLevel != null
      ? interviewsList.find(
          (i: any) =>
            isActiveInterviewStatus(i.status) &&
            userIsInterviewParticipant(i, currentUser?.id) &&
            Number(i.level) === stageInterviewLevel,
        )
      : undefined) ??
    interviewsList.find(
      (i: any) => isActiveInterviewStatus(i.status) && userIsInterviewParticipant(i, currentUser?.id),
    );

  /** Same stage + active interview + evaluator role — covers missing / partial participant rows. */
  const roleFallbackActiveInterview =
    stageInterviewLevel != null &&
    currentUser &&
    userRoleEligibleForInterviewLevel(currentUser, stageInterviewLevel)
      ? interviewsList.find(
          (i: any) =>
            Number(i.level) === stageInterviewLevel && isActiveInterviewStatus(i.status),
        )
      : undefined;

  const activeInterviewForUser = participantActiveInterview ?? roleFallbackActiveInterview;

  const lastInterviewForUser = interviewsList.find((i: any) => userIsInterviewParticipant(i, currentUser?.id));

  const currentUserEvaluation =
    activeInterviewForUser?.evaluations?.find((e: any) => sameUserId(e.evaluatorId, currentUser?.id)) ??
    lastInterviewForUser?.evaluations?.find((e: any) => sameUserId(e.evaluatorId, currentUser?.id));

  const isInterviewCompleted = (level: number) =>
    interviewsList.some((i: any) => Number(i.level) === level && isCompletedInterviewStatus(i.status));

  const isInterviewActive = (level: number) =>
    interviewsList.some((i: any) => Number(i.level) === level && isActiveInterviewStatus(i.status));

  const hasSubmittedFeedback = !!currentUserEvaluation;

  const policyManagedStages: Record<string, string> = {
    'Level 1 Interview Pending': 'INTERVIEW_LEVEL_1',
    'Level 2 Interview Pending': 'INTERVIEW_LEVEL_2',
    'Level 2 Recommended': 'INTERVIEW_LEVEL_2',
    'Level 3 Interview Pending': 'INTERVIEW_LEVEL_3',
    'LOI In Progress': 'LOI_APPROVAL',
    'LOA Pending': 'LOA_APPROVAL',
  };

  const currentStageCode = policyManagedStages[application?.status];
  const currentUserStageAction = application?.stageApprovals?.find(
    (a: any) => a.stageCode === currentStageCode && String(a.actorUserId) === String(currentUser?.id)
  );

  const getApplicationPermissions = () => {
    if (!application || !currentUser) {
      return {
        canApprove: false,
        canReject: false,
        canSchedule: false,
        canAssign: false,
        isLoaLocked: false,
        isSecurityDetailsLocked: false,
        showDecisionMessage: false,
      };
    }

    const isAdminRole = ['DD Admin', 'Super Admin', 'NBH', 'DD Lead', 'DD Head', 'Finance', 'Finance Admin', 'FDD', 'ZBH', 'RBM'].includes(currentUser.role);
    const isAdministrativeStage = [
      'Level 3 Approved', 'FDD Verification',
      'LOI In Progress', 'Security Details', 'Payment Pending', 'LOI Issued', 'Statutory LOI Ack',
      'Architecture Team Assigned', 'Architecture Document Upload', 'Architecture Team Completion',
      'Statutory GST', 'Statutory PAN', 'Statutory Nodal', 'Statutory Check',
      'Statutory Partnership', 'Statutory Firm Reg', 'Statutory Rental',
      'Statutory Virtual Code', 'Statutory Domain', 'Statutory MSD',
      'LOA Pending', 'EOR In Progress', 'EOR Complete', 'Inauguration', 'Approved',
    ].includes(application.status);

    const isLoaLocked = application.status === 'LOA Pending' && getDeposit('FIRST_FILL')?.status !== 'Verified';
    const isSecurityDetailsLocked =
      ['Security Details', 'Payment Pending'].includes(application.status) &&
      getDeposit('SECURITY_DEPOSIT')?.status !== 'Verified';
    const isFinalState = application.status === 'Onboarded' || application.status === 'Rejected';

    const ddHeadApproved = application.stageApprovals?.some((a: any) => a.stageCode === 'LOI_APPROVAL' && a.actorRole === 'DD Head' && a.decision === 'Approved');
    const ddHeadLoaApproved = application.stageApprovals?.some((a: any) => a.stageCode === 'LOA_APPROVAL' && a.actorRole === 'DD Head' && a.decision === 'Approved');

    let sequenceMet = true;
    if (!['Super Admin', 'DD Admin', 'DD Lead', 'DD Head'].includes(currentUser.role)) {
      if (application.status === 'FDD Verification' || application.status === 'Level 3 Approved') sequenceMet = false;
      if (application.status === 'LOI In Progress') sequenceMet = currentUser.role === 'NBH' ? !!ddHeadApproved : currentUser.role === 'DD Head';
      if (application.status === 'LOA Pending') sequenceMet = currentUser.role === 'NBH' ? !!ddHeadLoaApproved : currentUser.role === 'DD Head';
    }

    const hasMadeStageDecision = !!application.stageApprovals?.find(
      (a: any) => policyManagedStages[application.status] === a.stageCode && String(a.actorUserId) === String(currentUser.id)
    );
    const hasMadeInterviewDecision = ['Approved', 'Rejected', 'Selected'].includes(
      currentUserEvaluation?.decision || currentUserEvaluation?.recommendation || ''
    );

    const isDecisionMade = (activeInterviewForUser ? hasMadeInterviewDecision : false) || hasMadeStageDecision;
    const canApproveReject =
      !isFinalState &&
      !isDecisionMade &&
      (isAdminRole &&
        isAdministrativeStage &&
        sequenceMet &&
        (!['EOR In Progress', 'Inauguration', 'Approved'].includes(application.status) || eorProgress === 100));

    return {
      canApprove: canApproveReject && !isLoaLocked && !isSecurityDetailsLocked,
      canReject: canApproveReject && !isLoaLocked,
      isLoaLocked,
      isSecurityDetailsLocked,
      showDecisionMessage: isDecisionMade && (!isAdministrativeStage || hasMadeStageDecision),
      canSchedule:
        ['DD Admin', 'Super Admin', 'DD AM', 'ASM'].includes(currentUser.role) &&
        !isFinalState &&
        ![1, 2, 3].every((level) => interviewsList.some((i: any) => i.level === level)),
      canAssign: ['DD Admin', 'Super Admin', 'DD AM'].includes(currentUser.role),
    };
  };

  return {
    activeInterviewForUser,
    lastInterviewForUser,
    currentUserEvaluation,
    hasSubmittedFeedback,
    currentUserStageAction,
    isInterviewCompleted,
    isInterviewActive,
    permissions: getApplicationPermissions(),
  };
}
