import { BaseRepositoryPort } from '@humand-packages/common';
import {
    TimeTrackingCategorizedHourApprovalStep,
    TimeTrackingCategorizedHourApprovalStepForCreation,
} from '../../../business/models/timeTracking/timeTrackingCategorizedHourApprovalStep';
import {
    TimeTrackingCategorizedHourApprovalStepPotentialApprover,
    TimeTrackingCategorizedHourApprovalStepPotentialApproverForCreation,
} from '../../../business/models/timeTracking/timeTrackingCategorizedHourApprovalStepPotentialApprover';
import { TimeTrackingCategorizedHourApprovalStepState } from '../../constants/timeTracking/categorizedHourApprovalStepStates';

export abstract class TimeTrackingCategorizedHourApprovalStepRepositoryPort extends BaseRepositoryPort {
    abstract bulkCreateCategorizedHourApprovalSteps(
        steps: TimeTrackingCategorizedHourApprovalStepForCreation[],
    ): Promise<TimeTrackingCategorizedHourApprovalStep[]>;

    abstract bulkCreateCategorizedHourApprovalStepPotentialApprovers(
        items: TimeTrackingCategorizedHourApprovalStepPotentialApproverForCreation[],
    ): Promise<TimeTrackingCategorizedHourApprovalStepPotentialApprover[]>;

    abstract listCategorizedHourApprovalSteps(categorizedHourId: string, instanceId: number): Promise<TimeTrackingCategorizedHourApprovalStep[]>;

    /** Finds a step for admin (no approver restriction) */
    abstract findCategorizedHourApprovalStep(
        stepId: string,
        categorizedHourId: string,
        instanceId: number,
    ): Promise<TimeTrackingCategorizedHourApprovalStep>;

    /** Finds an actionable step (PENDING, APPROVED, or REJECTED) only if the given userId is a potential approver */
    abstract findCategorizedHourApprovalStepForApprover(
        stepId: string,
        categorizedHourId: string,
        userId: number,
    ): Promise<TimeTrackingCategorizedHourApprovalStep | null>;

    abstract updateCategorizedHourApprovalStep(step: TimeTrackingCategorizedHourApprovalStep): Promise<TimeTrackingCategorizedHourApprovalStep>;

    /** Returns distinct categorized hour IDs where the user is a potential approver of an actionable step */
    abstract getCategorizedHourIdsForApprover(userId: number, instanceId: number): Promise<string[]>;

    abstract getStepIdsWhereUserIsPotentialApprover(userId: number, stepIds: string[]): Promise<string[]>;

    abstract getCurrentStepIdsByCategorizedHourIds(categorizedHourIds: string[]): Promise<Map<string, string>>;

    abstract deleteApprovalDataByCategorizedHourIds(categorizedHourIds: string[]): Promise<void>;

    abstract classifyForBulkReview(input: { instanceId: number; hourIds: string[]; loggedUserId: number }): Promise<{
        toReview: Array<{ hourId: string; stepId: string; position: number }>;
        skippedCount: number;
    }>;

    abstract executeBulkReview(input: {
        stepIds: string[];
        approverId: number;
        state: TimeTrackingCategorizedHourApprovalStepState.APPROVED | TimeTrackingCategorizedHourApprovalStepState.REJECTED;
        comment: string | null;
    }): Promise<{
        reviewed: Array<{ stepId: string; hourId: string }>;
        concurrencyLosers: string[];
    }>;
}
