import { OrderItem, BasePort, LanguagesValues } from '@humand-packages/common';
import { Service } from 'typedi';
import { UpdateWorkSchedule, UpdateWorkScheduleDataResult } from '../../../../types/bulkUploads/checkDataResult';
import { MethodParams } from '../../../../types/bulkUploads/runJobDTO';
import { UserInterface } from '../../../users/business/models/userInterface';
import { WorkScheduleUsersDAOCreationAttributes } from '../../infrastructure/dataAccessObjects/workScheduleUsers';
import { ScheduleFilter } from '../interfaces/timeTrackingDaySummaryFilters';
import { WorkScheduleUserAssignmentAttributes } from '../interfaces/WorkScheduleUserAssignmentAttributes';
import { WorkScheduleUserAssignmentFilters } from '../interfaces/workScheduleUserAssignmentFilters';
import {
    AssignedWorkSchedule,
    WorkScheduleUserAssignment,
    WorkSchedule,
    WorkScheduleCreationParameters,
    WorkScheduleUpdateAttributes,
} from '../models/workSchedule';
import { WorkSchedulesSearchFilters } from '../models/workScheduleSearchFilters';

@Service()
export default abstract class WorkScheduleServicePort extends BasePort {
    abstract createSchedule(params: WorkScheduleCreationParameters): 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): Promise<WorkSchedule>;
    abstract getWorkScheduleByUser(userId: number, instanceId: number, timezone: string): Promise<WorkSchedule | undefined>;
    abstract getWorkScheduleByUserIds(userIds: number[], instanceId: number, timezone: string): Promise<{ [userId: number]: AssignedWorkSchedule }>;
    abstract assignWorkScheduleToUser(userId: number, workScheduleId: number, instanceId: number, timezone: string): Promise<WorkSchedule>;
    abstract unassignWorkScheduleFromUser(userId: number, instanceId: number, timezone: string): Promise<void>;
    abstract getAssignedWorkSchedulesByUser(userId: number, instanceId: number, fromDate: string, toDate: string): Promise<AssignedWorkSchedule[]>;
    abstract eliminateWorkSchedule(id: number, instanceId: number): Promise<void>;
    abstract updateWorkSchedule(instanceId: number, id: number, attributes: WorkScheduleUpdateAttributes, timezone: string): Promise<WorkSchedule>;
    abstract assignUsersToSchedule(params: WorkScheduleUserAssignmentAttributes, timezone: string): Promise<void>;
    abstract getWorkSchedulesByXlsxBuffer(buffer: Buffer, user: UserInterface): Promise<Record<string, string>[]>;
    abstract getUpdateWorkSchedulesDataByXlsx(inputData: Record<string, unknown>, params: MethodParams): Promise<UpdateWorkScheduleDataResult>;
    abstract bulkUpdateWorkSchedules(updateUsersData: UpdateWorkSchedule[], params: MethodParams): Promise<void>;
    abstract migrateWorkdaysToWorkSchedules(
        devopsUser: UserInterface,
        limit: number,
    ): Promise<{ [instanceId: number]: { instanceName: string; amountMigrated: number } }>;

    abstract getAssignedWorkSchedulesBySchedule(
        id: number,
        instanceId: number,
        pagination: { limit: number; offset: number },
    ): Promise<{ count: number; rows: AssignedWorkSchedule[] }>;

    abstract bulkCreateAssignments(assignments: WorkScheduleUsersDAOCreationAttributes[]): Promise<void>;
    abstract deleteExistingWorkSchedules(instanceId: number): Promise<void>;
    abstract getAllUsersAssignedToWorkSchedule(
        id: number,
        instanceId: number,
        loggedUser: UserInterface,
        pagination: { limit: number; offset: number },
        timezone: string,
        filters: WorkScheduleUserAssignmentFilters,
    ): 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, instanceId: number): Promise<void>;
    abstract getWorkScheduleTranslations(language: LanguagesValues): Record<string, string>;
    abstract getUserIdsByScheduleCriteria(
        instanceId: number,
        userIds: number[],
        fromDate: string,
        toDate: string,
        filters: ScheduleFilter,
    ): Promise<number[]>;
}
