import { BaseAdapter, Events } from '@humand-packages/common';
import { Service } from 'typedi';
import { PortsDI } from '../../../../config/portsDI';
import { EventEmitterService } from '../../../../services/eventEmitter';
import { NightShiftAssignment } from '../../infrastructure/constants/setting';
import TimeTrackingPoliciesRepositoryPort from '../../infrastructure/ports/TimeTrackingPoliciesRepositoryPort';
import TimeTrackingSettingRepositoryPort from '../../infrastructure/ports/TimeTrackingSettingRepositoryPort';
import { TimeTrackingSetting, TimeTrackingSettingForCreation } from '../models/timeTrackingSetting';

@Service()
export default class TimeTrackingSettingService extends BaseAdapter {
    constructor(
        @PortsDI(TimeTrackingSettingRepositoryPort) private readonly settingRepository: TimeTrackingSettingRepositoryPort,
        @PortsDI(TimeTrackingPoliciesRepositoryPort) private readonly policiesRepository: TimeTrackingPoliciesRepositoryPort,
        private readonly eventEmitterService: EventEmitterService,
    ) {
        super();
    }

    public create = async (setting: TimeTrackingSettingForCreation): Promise<TimeTrackingSetting> => {
        return await this.settingRepository.create(setting);
    };

    public getByInstanceId = async (instanceId: number): Promise<TimeTrackingSetting> => {
        const setting = await this.settingRepository.getByInstanceId(instanceId);
        if (setting) {
            return setting;
        } else {
            const count = await this.policiesRepository.countPoliciesByInstance(instanceId);
            const defaultSetting = {
                instanceId,
                nightShiftAssignment: count ? NightShiftAssignment.CALENDAR_DATE : NightShiftAssignment.SCHEDULE_INIT,
            } as TimeTrackingSettingForCreation;
            return await this.settingRepository.create(defaultSetting);
        }
    };

    public update = async (instanceId: number, newAttributes: Partial<TimeTrackingSettingForCreation>): Promise<TimeTrackingSetting> => {
        const oldAttributes = await this.getByInstanceId(instanceId);
        const cleanAttributes = Object.fromEntries(
            Object.entries(newAttributes).filter(([_, value]) => value !== undefined),
        ) as Partial<TimeTrackingSettingForCreation>;
        const updatedSetting = await this.settingRepository.update(
            new TimeTrackingSetting({
                ...oldAttributes,
                ...cleanAttributes,
            }),
        );
        this.eventEmitterService.emitEvent(Events.TIME_TRACKING_SETTING_UPDATED, {
            instanceId,
            setting: { nightShiftAssignment: updatedSetting.nightShiftAssignment },
        });
        return updatedSetting;
    };
}
