import { NotFoundException } from "@nestjs/common";
import { PrismaClientKnownRequestError } from "@prisma/client/runtime/client";
import { PrismaPostgresService, TransactionClient } from "prisma/postgres/prisma-postgres.service";


type UpdatableDelegate<T> = {
    update(args: {
        where: { id: number },
        data: { is_approved: boolean },
    }): Promise<T>;
};

//abstract class for approving or rejecting a shift, expense, timesheet or pay-period
export abstract class BaseApprovalService<T> {
    protected constructor(protected readonly prisma: PrismaPostgresService) { }

    //returns the corresponding Prisma delegate
    protected abstract get delegate(): UpdatableDelegate<T>;

    protected abstract delegateFor(tx: TransactionClient): UpdatableDelegate<T>;

    //standard update Aproval
    async updateApproval(id: number, is_approved: boolean): Promise<T> {
        try {
            return await this.delegate.update({
                where: { id },
                data: { is_approved: is_approved },
            });
        } catch (error: any) {
            if (error instanceof PrismaClientKnownRequestError && error.code === "P2025") {
                throw new NotFoundException(`Entity #${id} not found`);
            }
            throw error;
        }
    }

    async updateApprovalWithTransaction(tx: TransactionClient, id: number, is_approved: boolean): Promise<T> {
        try {
            return await this.delegateFor(tx).update({
                where: { id },
                data: { is_approved: is_approved },
            });
        } catch (error: any) {
            if (error instanceof PrismaClientKnownRequestError && error.code === 'P2025') {
                throw new NotFoundException(`Entity #${id} not found`);
            }
            throw error;
        }
    }
} 