import { WORKDAYS } from '@humand-packages/common';
import {
    AutoIncrement,
    BelongsTo,
    Column,
    CreatedAt,
    DataType,
    DeletedAt,
    ForeignKey,
    HasMany,
    HasOne,
    Index,
    Model,
    PrimaryKey,
    Table,
    UpdatedAt,
} from 'sequelize-typescript';
import { InstanceDAO } from '../../../instances/infrastructure/dataAccessObjects/instanceDAO';
import { TimeTrackingPolicyAutoCloseMode } from '../../business/enum/timeTracking/policy';
import { TimeSlot } from '../../business/models/timeTracking/scheduleData';
import { DaySummaryScheduleSource } from '../../business/types/scheduleSource';
import { Incidence } from '../constants/incidences';
import { State } from '../constants/state';
import { TimeTrackingDaySummaryHolidayDAO } from './daySummaryHoliday';
import { TimeTrackingDaySummaryTimeOffDAO } from './daySummaryTimeOff';
import { TimeTrackingEntryDAO } from './entry';
import { TimeTrackingPoliciesHistoryDAO } from './policyHistory';
import { ShiftAssignedDayDAO } from './shiftManagement/shiftAssignedDay';
import { WorkScheduleDAO } from './workSchedule';

export interface TimeTrackingDaySummaryCreationAttributes {
    date: Date;
    dateString: string;
    userId: number;
    workScheduleId?: number;
    scheduleDayId?: number;
    weekday?: WORKDAYS;
    estimatedHours: number;
    workedHours: number;
    scheduledHours: number;
    incidences: Incidence[];
    state: State;
    dayChange: Date;
    autoCloseTime?: Date;
    autoCloseMode: TimeTrackingPolicyAutoCloseMode;
    autoCloseEntryTime?: Date;
    instanceId: number;
    timeSlots: Array<TimeSlot> | null;
    nightShift: boolean;
    isWorkday: boolean;
    timeOffHours: number | null;
}

@Table({
    indexes: [
        {
            fields: ['dateString', 'userId'],
            name: 'time_tracking_day_summaries_user_id_date_unique',
            unique: true,
            where: {
                deletedAt: null,
            },
        },
    ],
    tableName: 'TimeTrackingDaySummaries',
})
export class TimeTrackingDaySummaryDAO extends Model<TimeTrackingDaySummaryDAO, TimeTrackingDaySummaryCreationAttributes> {
    @PrimaryKey
    @AutoIncrement
    @Column
    id!: number;

    @Column(DataType.DATE)
    date!: Date;

    @Index('time_tracking_day_summaries_user_id_date_unique')
    @Column(DataType.STRING)
    dateString!: string;

    @Index('time_tracking_day_summaries_user_id_date_unique')
    @Column
    userId!: number;

    @ForeignKey(() => WorkScheduleDAO)
    @Column
    workScheduleId?: number;

    @ForeignKey(() => ShiftAssignedDayDAO)
    @Column
    shiftAssignedDayId?: number;

    @Column(DataType.ENUM(...Object.values(WORKDAYS)))
    weekday!: WORKDAYS;

    // Its a copy of time slots associated to the scheduled day, to avoid needing to fetch from database every time
    // Has potential to be used later as single day schedule override.
    @Column(DataType.JSONB)
    timeSlots!: Array<TimeSlot> | null;

    @Column(DataType.FLOAT)
    estimatedHours!: number; // scheduled - time off and or holidays

    @Column(DataType.FLOAT)
    workedHours!: number;

    @Column(DataType.FLOAT)
    timeOffHours!: number | null;

    @Column(DataType.FLOAT)
    scheduledHours!: number | null; // hours scheduled, ignoring time off but accounting for holidays

    @Column(DataType.ENUM(...Object.values(DaySummaryScheduleSource)))
    scheduleSource!: DaySummaryScheduleSource;

    @Column(DataType.ARRAY(DataType.STRING))
    incidences!: Incidence[];

    @ForeignKey(() => InstanceDAO)
    @Column
    instanceId!: number;

    @Column(DataType.DATE)
    dayChange!: Date;

    @Column(DataType.DATE)
    autoCloseTime?: Date;

    @Column(DataType.STRING)
    autoCloseMode!: TimeTrackingPolicyAutoCloseMode;

    @Column(DataType.DATE)
    autoCloseEntryTime?: Date;

    @Column(DataType.STRING)
    state!: State;

    @Column
    nightShift!: boolean;

    @Column
    isWorkday!: boolean;

    @CreatedAt
    @Column(DataType.DATE)
    createdAt!: Date;

    @UpdatedAt
    @Column(DataType.DATE)
    updatedAt!: Date;

    @DeletedAt
    @Column(DataType.DATE)
    deletedAt!: Date | null;

    @BelongsTo(() => WorkScheduleDAO)
    workSchedule!: WorkScheduleDAO;

    @HasMany(() => TimeTrackingEntryDAO)
    timeTrackingEntries!: TimeTrackingEntryDAO[];

    @HasMany(() => TimeTrackingDaySummaryHolidayDAO)
    holidays!: TimeTrackingDaySummaryHolidayDAO[];

    @HasMany(() => TimeTrackingDaySummaryTimeOffDAO)
    timeOffRequests!: TimeTrackingDaySummaryTimeOffDAO[];

    @HasOne(() => TimeTrackingPoliciesHistoryDAO)
    policyHistory!: TimeTrackingPoliciesHistoryDAO;
}
