import { OptionalLimitOffsetPagination, BaseRepositoryPort } from '@humand-packages/common';
import { Order } from 'sequelize';
import { Instance } from '../../../instances/business/models/instance';
import { Holiday } from '../../../regions/business/models/holiday';
import { TimeOffRequest } from '../../../timeOff/business/models/requests/timeOffRequest';
import { TIME_OFF_POLICY_TYPE_ACTIVITY_TYPES } from '../../../timeOff/business/types/policyTypes/activityTypes';
import { GridFilterRequest } from '../../business/interfaces/shiftManagement/gridFiltersInterface';
import { TimeTrackingDaySummaryWithInstanceFilters } from '../../business/interfaces/timeTrackingDaySummaryFilters';
import { TimeTrackingDaySummary } from '../../business/models/daySummary';
import { TimeTrackingEntry, TimeTrackingEntryPrototype } from '../../business/models/timeTrackingEntry';
import { Incidence } from '../constants/incidences';
import { State } from '../constants/state';
import { TimeTrackingDaySummaryCreationAttributes } from '../dataAccessObjects/daySummary';

export abstract class TimeTrackingRepositoryPort extends BaseRepositoryPort {
    abstract createEntry(entry: TimeTrackingEntryPrototype): Promise<TimeTrackingEntry>;
    abstract updateEntry(entry: Partial<TimeTrackingEntry>): Promise<TimeTrackingEntry | undefined>;
    abstract createBulkEntries(entries: TimeTrackingEntryPrototype[]): Promise<TimeTrackingEntry[]>;
    abstract listEntries(
        userId: number,
        fromDate: Date,
        toDate: Date,
        pagination: OptionalLimitOffsetPagination,
        order?: Order,
    ): Promise<{ count: number; rows: TimeTrackingEntry[] }>;

    abstract getDaySummariesForAutoClose(date: Date, fromDate: Date, limit: number): Promise<TimeTrackingDaySummary[]>;
    abstract getDaySummariesForDayChange(date: Date, fromDate: Date, limit: number): Promise<TimeTrackingDaySummary[]>;
    abstract deleteEntry(entry: TimeTrackingEntry): Promise<void>;
    abstract getDaySummaryById(instanceId: number, id: number): Promise<TimeTrackingDaySummary | undefined>;
    abstract getDaySummary(userId: number, date: string): Promise<TimeTrackingDaySummary | undefined>;
    abstract createDaySummary(
        daySummary: TimeTrackingDaySummaryCreationAttributes,
        holidays: Holiday[],
        timeOffRequests: TimeOffRequest[],
    ): Promise<TimeTrackingDaySummary>;

    abstract updateDaySummary(id: number, daySummary: Partial<TimeTrackingDaySummaryCreationAttributes>): Promise<void>;
    abstract addTimeOffRequestToDaySummary(
        activityType: TIME_OFF_POLICY_TYPE_ACTIVITY_TYPES | null,
        daySummaryId: number,
        requestId: number,
        policyTypeName: string,
        policyTypeIcon: string | null,
        hours: number | null,
        consumptionType: string,
        fromTime?: string | null,
        toTime?: string | null,
        fromDate?: string | null,
        toDate?: string | null,
    ): Promise<void>;

    abstract removeTimeOffRequestFromDaySummary(daySummaryId: number, timeOffRequestId: number): Promise<void>;
    abstract updateDaySummaryAfterEntryChanges(
        id: number,
        workedHours: number,
        incidences: Incidence[],
        state: State,
        autoCloseTime?: Date,
        autoCloseEntryTime?: Date,
    ): Promise<void>;

    abstract getDaySummariesByUser(userId: number, fromDate: string, toDate: string, includeEntries?: boolean): Promise<TimeTrackingDaySummary[]>;
    abstract createDaySummaries(daySummaries: Partial<TimeTrackingDaySummary>[], instance: Instance): Promise<TimeTrackingDaySummary[]>;
    abstract updateDaySummaries(
        daySummaries: { autoCloseEntryTime?: Date; autoCloseTime?: Date; id: number; incidences?: Incidence[]; state: State; workedHours: number }[],
    ): Promise<void>;

    abstract getDaySummariesByInstanceAndDate(instanceId: number, date: string): Promise<TimeTrackingDaySummary[]>;
    abstract getDaySummariesForUsersOnDates(userIds: number[], dateStrings: string[]): Promise<TimeTrackingDaySummary[]>;
    abstract addHolidayToDaySummary(daySummaryId: number, holidayId: number, holidayName: string): Promise<void>;
    abstract removeHolidayFromDaySummary(daySummaryId: number, holidayId: number): Promise<void>;
    abstract deleteDaySummariesForUsers(userIds: number[], fromDate: string, endDate?: string): Promise<void>;
    abstract deleteDaySummariesForInstance(instance: number, fromDate: string): Promise<void>;
    abstract searchUserIdsByDaySummaries(filters: TimeTrackingDaySummaryWithInstanceFilters): Promise<number[]>;
    abstract searchUserIdsWithMissingSummaries(userIds: number[], fromDate: string, toDate: string): Promise<number[]>;
    abstract getEntriesOfInstance(instanceId: number, fromDate: Date, limit: number): Promise<{ count: number; rows: TimeTrackingEntry[] }>;
    abstract updateEntriesSummaryId(summaryId: number, entryIds: number[]): Promise<TimeTrackingEntry[]>;
    abstract filterUsersBySites(
        instanceId: number,
        userIds: number[],
        fromDate: string,
        toDate: string,
        siteIds?: number[],
        excludeSiteIds?: number[],
    ): Promise<number[]>;

    abstract getTimeTrackingPolicyHistoryLatenessTolerance(
        userId: number,
        fromDate: string,
        toDate: string,
    ): Promise<Array<{ dateString: string; latenessTolerance: number | null }>>;

    abstract getDaySummariesByUsers(userIds: number[], fromDate: string, toDate: string): Promise<TimeTrackingDaySummary[]>;
    abstract deleteDaySummariesByGridFilters(instanceId: number, filters: GridFilterRequest): Promise<void>;
    abstract getDaySummariesToCorrectByGridFilters(filters: GridFilterRequest, limit: number): Promise<TimeTrackingDaySummary[]>;
    abstract deleteDaySummariesByShiftAssignedDayId(instanceId: number, shiftAssignedDayId: number): Promise<void>;
    abstract bulkDeleteEntries(instanceId: number, entryIds: number[]): Promise<void>;
}
