import { Injectable } from "@nestjs/common";
import { PrismaPostgresService } from "prisma/postgres/prisma-postgres.service";
import { computePeriod, listPayYear, payYearOfDate } from "src/common/utils/date-utils";
import { PayPeriodDto } from "../dtos/overview-pay-period.dto";
import { Result } from "src/common/errors/result-error.factory";
import { mapPayPeriodToDto } from "src/time-and-attendance/pay-period/pay-periods.mapper";

@Injectable()
export class PayPeriodsQueryService {
    constructor(
        private readonly prisma: PrismaPostgresService) { }

    async findOneByYearPeriod(pay_year: number, period_no: number): Promise<Result<PayPeriodDto, string>> {
        const row = await this.prisma.payPeriods.findFirst({
            where: { pay_year, pay_period_no: period_no },
        });
        if (row) return { success: true, data: mapPayPeriodToDto(row) };

        // fallback for outside of view periods
        const period = computePeriod(pay_year, period_no);
        return {
            success: true,
            data: {
                pay_period_no: period.period_no,
                pay_year: period.pay_year,
                period_start: period.period_start,
                payday: period.payday,
                period_end: period.period_end,
                label: period.label
            }
        }
    }

    //function to cherry pick a Date to find a period
    async findByDate(date: string): Promise<Result<PayPeriodDto, string>> {
        const dt = new Date(date);
        const row = await this.prisma.payPeriods.findFirst({
            where: { period_start: { lte: dt }, period_end: { gte: dt } },
        });
        if (row) return { success: true, data: mapPayPeriodToDto(row) };

        //fallback for outwside view periods
        const pay_year = payYearOfDate(date);
        const periods = listPayYear(pay_year);
        const hit = periods.find(period => date >= period.period_start && date <= period.period_end);
        if (!hit) return { success: false, error: `PAY_PERIOD_NOT_FOUND` }

        return {
            success: true,
            data: {
                pay_period_no: hit.period_no,
                pay_year: hit.pay_year,
                period_start: hit.period_start,
                period_end: hit.period_end,
                payday: hit.payday,
                label: hit.label
            }
        }
    }
}
