import { WORKDAYS, OrderItem, BaseRepositoryPort } from '@humand-packages/common';
import { ScheduleFilter } from '../../business/interfaces/timeTrackingDaySummaryFilters';
import { WorkScheduleUserAssignmentAttributes } from '../../business/interfaces/WorkScheduleUserAssignmentAttributes';
import {
    AssignedWorkSchedule,
    WorkSchedule,
    WorkScheduleCreationAttributes,
    WorkScheduleSimpleUpdateAttributes,
    WorkScheduleUser,
    WorkScheduleUserAssignment,
} from '../../business/models/workSchedule';
import { WorkSchedulesSearchFilters } from '../../business/models/workScheduleSearchFilters';
import { WorkScheduleUsersDAOCreationAttributes } from '../dataAccessObjects/workScheduleUsers';

export abstract class WorkScheduleRepositoryPort extends BaseRepositoryPort {
    abstract createSchedule(params: WorkScheduleCreationAttributes): Promise<WorkSchedule>;
    abstract listWorkSchedules(
        params: WorkSchedulesSearchFilters,
        pagination: { limit: number; offset: number },
        order?: OrderItem[],
    ): Promise<{ count: number; rows: WorkSchedule[] }>;

    abstract getWorkSchedule(
        id: number,
        instanceId: number,
        timezone: string,
        includeCollaborators?: boolean,
        excludeDeleted?: boolean,
    ): Promise<WorkSchedule>;

    abstract getWorkScheduleByUser(userId: number, instanceId: number, timezone: string): Promise<WorkSchedule | undefined>;
    abstract getWorkSchedulesByUsers(userIds: number[], instanceId: number, timezone: string): Promise<AssignedWorkSchedule[]>;
    abstract getAssignedWorkSchedulesByUser(userId: number, instanceId: number, fromDate: string, toDate: string): Promise<AssignedWorkSchedule[]>;
    abstract getAssignedWorkSchedulesBySchedule(
        id: number,
        instanceId: number,
        pagination: { limit: number; offset: number },
    ): Promise<{ count: number; rows: AssignedWorkSchedule[] }>;

    // Returns affected users
    abstract eliminateWorkSchedule(id: number, newScheduleId?: number): Promise<number[]>;
    abstract updateWorkSchedule(previousId: number, params: WorkScheduleSimpleUpdateAttributes): Promise<WorkSchedule>;
    abstract listSimilarAutoCreatedWorkSchedules(instanceId: number, hashes: string[]): Promise<WorkSchedule[]>;
    abstract assignUsers(params: WorkScheduleUserAssignmentAttributes, timezone: string): Promise<void>;
    abstract unassignUsers(userIds: number[]): Promise<void>;
    abstract getUsersWithoutWorkSchedulesWithWorkdays(
        limit: number,
    ): Promise<{ instance: { id: number; name: string }; users: { id: number; workdays: WORKDAYS[] }[] }[]>;

    abstract bulkCreateAssignments(assignments: WorkScheduleUsersDAOCreationAttributes[]): Promise<void>;
    abstract listWorkScheduleIdsByInstance(
        instanceId: number,
        pagination: { limit: number; offset: number },
    ): Promise<{ count: number; rows: number[] }>;

    abstract getAllUsersAssignedToWorkSchedule(
        id: number,
        instanceId: number,
        userIds: number[],
        pagination: { limit: number; offset: number },
        timezone: string,
    ): Promise<{ count: number; rows: WorkScheduleUserAssignment[] }>;

    abstract getAllUserAssignmentsInWorkSchedule(
        id: number,
        instanceId: number,
        userId: number,
        pagination: { limit: number; offset: number },
        timezone: string,
    ): Promise<{ count: number; rows: WorkScheduleUserAssignment[] }>;

    abstract deleteWorkScheduleUser(id: number, workScheduleId: number): Promise<void>;
    abstract getWorkScheduleUser(id: number, workScheduleId: number): Promise<WorkScheduleUser | null>;
    abstract getUserIdsByScheduleCriteria(
        instanceId: number,
        userIds: number[],
        fromDate: string,
        toDate: string,
        filters: ScheduleFilter,
    ): Promise<number[]>;
}
