import { Injectable } from "@nestjs/common";
import { Result } from "src/common/errors/result-error.factory";
import { PrismaPostgresService } from "prisma/postgres/prisma-postgres.service";

@Injectable()
export class BankedHoursService {

    constructor(private readonly prisma: PrismaPostgresService) { }

    //manage shifts with bank_code.type BANKING
    manageBankingHours = async (employee_id: number, asked_hours: number, type: string): Promise<Result<number, string>> => {
        if (asked_hours <= 0) return { success: false, error: 'INVALID_BANKING_HOURS' };

        try {
            const result = await this.prisma.$transaction(async (tx) => {
                const employee = await this.prisma.employees.findUnique({
                    where: { id: employee_id },
                    select: {
                        id: true,
                        paid_time_off: {
                            select: {
                                banked_hours: true
                            },
                        },
                    },
                });

                if (!employee) {
                    return { success: false, error: 'EMPLOYEE_NOT_FOUND' } as Result<number, string>;
                }
                if (!employee.paid_time_off) {
                    return { success: false, error: 'BANKING_HOURS_BANK_NOT_FOUND' } as Result<number, string>;
                }
                const banked_hours = (employee.paid_time_off.banked_hours).toNumber();
                if (banked_hours <= 0 && type === 'WITHDRAW_BANKED') {
                    return { success: false, error: 'EMPTY_BANKED_HOURS' } as Result<number, string>;
                }

                if (type === 'BANKING') {
                    const new_balance = await tx.paidTimeOff.update({
                        where: { employee_id: employee.id },
                        data: {
                            banked_hours: { increment: (asked_hours) },
                            last_updated: new Date(),
                        },
                        select: { banked_hours: true },
                    });
                    return { success: true, data: (new_balance.banked_hours).toNumber() } as Result<number, string>;

                } else if (type === 'WITHDRAW_BANKED') {
                    if (asked_hours > banked_hours) {
                        return { success: true, data: banked_hours } as Result<number, string>;
                    } else {

                    }
                    await tx.paidTimeOff.update({
                        where: { employee_id: employee.id },
                        data: {
                            banked_hours: { decrement: asked_hours },
                            last_updated: new Date(),
                        },
                        select: { banked_hours: true },
                    });
                    return { success: true, data: asked_hours } as Result<number, string>;
                } else {
                    return { success: false, error: 'INVALID_SHIFT_TYPE' } as Result<number, string>;
                }
            });
            return result;

        } catch (error) {
            return { success: false, error: 'INVALID_BANKING_SHIFT' };
        }
    }
}