import { BaseRepositoryPort } from '@humand-packages/common';
import TimeTrackingPoliciesFilters from '../../business/interfaces/timeTrackingPoliciesFilters';
import TimeTrackingPoliciesOptions from '../../business/interfaces/timeTrackingPoliciesOptions';
import TimeTrackingPoliciesSearchFilters from '../../business/interfaces/timeTrackingPoliciesSearchFilters';
import TimeTrackingPoliciesUsersSearchFilters from '../../business/interfaces/timeTrackingPoliciesUsersSearchsFilters';
import { TimeTrackingPolicy, TimeTrackingPolicyAssociation, TimeTrackingPolicyForCreation } from '../../business/models/timeTrackingPolicy';
import { TimeTrackingPolicyHourCategoryAssociation } from '../../business/models/TimeTrackingPolicyHourCategory';
import { TimeTrackingSetting } from '../../business/models/timeTrackingSetting';
import { TimeTrackingPolicyUser } from '../dataAccessObjects/policyUsers';

export default abstract class TimeTrackingPoliciesRepositoryPort extends BaseRepositoryPort {
    abstract listPolicies(
        policiesFilters: TimeTrackingPoliciesFilters,
        options: TimeTrackingPoliciesOptions,
    ): Promise<{ count: number; rows: TimeTrackingPolicy[] }>;

    abstract listPolicyAssociations(
        policiesFilters: TimeTrackingPoliciesFilters,
        options: TimeTrackingPoliciesOptions,
    ): Promise<{ count: number; rows: TimeTrackingPolicyAssociation[] }>;

    /** Returns policy associations where toDate is null (active assignment per user). */
    abstract listActivePolicyAssociations(instanceId: number, userIds: number[]): Promise<TimeTrackingPolicyAssociation[]>;

    abstract listPolicyAssociationsEndedAt(instanceId: number, toDate: string, userIds: number[]): Promise<TimeTrackingPolicyAssociation[]>;

    abstract getPolicyByIdOrFail(instanceId: number, policyId: number): Promise<TimeTrackingPolicy>;

    abstract createPolicy(instanceId: number, policy: TimeTrackingPolicyForCreation): Promise<TimeTrackingPolicy>;

    abstract updatePolicy(updatedPolicy: TimeTrackingPolicy, historyInvalidationFromDate: string | null): Promise<TimeTrackingPolicy>;

    abstract associatePolicy(
        policyId: number,
        userIds: number[],
        fromDate: string,
        allUsers: boolean,
    ): Promise<{
        usersNewlyAssigned: number[];
        usersNowUnassigned: number[];
    }>;

    abstract eliminatePolicy(policyId: number, instanceId: number): Promise<void>;

    abstract listPoliciesUsers(
        instanceId: number,
        filters: {
            policyFilters?: Partial<TimeTrackingPoliciesSearchFilters>;
            policyUserFilters?: Partial<TimeTrackingPoliciesUsersSearchFilters>;
        },
    ): Promise<TimeTrackingPolicyUser[]>;

    abstract syncFaceRecognitionConfigurationForUsers(instanceId: number, userIds: number[]): Promise<void>;

    abstract getPoliciesOfInstance(instanceId: number): Promise<TimeTrackingPolicy[]>;

    abstract updateSettingsInPolicies(instanceId: number, settings: Partial<TimeTrackingSetting>): Promise<number[]>;
    abstract associatePolicyHourCategories(
        policyId: number,
        policyHourCategories: Array<TimeTrackingPolicyHourCategoryAssociation>,
        instanceId: number,
    ): Promise<number[]>;

    abstract countPoliciesByInstance(instanceId: number): Promise<number>;

    abstract listPoliciesByIds(policyIds: number[]): Promise<TimeTrackingPolicy[]>;
}
