import { Injectable, Logger } from '@nestjs/common';
import { CreateMatrixDto } from './dto/create-matrix.dto';
import { UpdateMatrixDto } from './dto/update-matrix.dto';
import { PrismaService } from 'src/prisma/prisma.service';

@Injectable()
export class MatricesService {
	constructor(private prisma: PrismaService) {}
	private readonly logger = new Logger(MatricesService.name);

	createMatrix(createMatrixDto: CreateMatrixDto) {
		const transaction = this.prisma.$transaction(async (tx) => {
			this.logger.log({ level: 'info', message: `Creating a new matrix with data: ${JSON.stringify(createMatrixDto)}`, refCode: '41201' });
			// change to use pricing matrix
			return tx.pricingmatrix.create({
				data: {
					...createMatrixDto,
					tableName: createMatrixDto.tableName || 'primary',
					type: createMatrixDto.type || 'screen printing',
				},
			});
			// return tx.primarymatrix.create({ data: createMatrixDto });
		});
		return transaction;
	}

	createRow(createMatrixDto: CreateMatrixDto[]) {
		const transaction = this.prisma.$transaction(async (tx) => {
			this.logger.log({ level: 'info', message: `Creating multiple matrices with data: ${JSON.stringify(createMatrixDto)}`, refCode: '41201' });
			// change to use pricing matrix
			return tx.pricingmatrix.createMany({
				data: createMatrixDto.map((dto) => ({
					...dto,
					tableName: dto.tableName || 'primary',
					type: dto.type || 'screen printing',
				})),
			});
			// return tx.primarymatrix.createMany({ data: createMatrixDto });
		});
		return transaction;
	}

	findPrimary() {
		const transaction = this.prisma.$transaction(async (tx) => {
			// this.logger.log({ level: 'info', message: 'Returning all primary matrices', refCode: '41202' });

			// change to use pricing matrix
			this.logger.log({ level: 'info', message: 'Returning all primary matrices', refCode: '41202' });
			const matix = tx.pricingmatrix.findMany({
				where: {
					tableName: 'primary',
					type: 'screen printing',
				},
			});

			return matix;
			// return tx.primarymatrix.findMany();
		});
		return transaction;
	}

	findAllPrimary(page = 1, take = 100, sortBy: string, sortOrder: string, search: string = '') {
		const transaction = this.prisma.$transaction(async (tx) => {
			const skip = (page - 1) * take; // Calculate the number of records to skip based on the page number
			this.logger.log({ level: 'info', message: `Returning all primary matrices with pagination, page: ${page}, take: ${take}, sortBy: ${sortBy}, sortOrder: ${sortOrder}, search: ${search}`, refCode: '41202' });
			return tx.pricingmatrix.findManyAndCount({
				skip: skip,
				take: take,
				orderBy: {
					[sortBy]: sortOrder,
				},
				where: {
					tableName: 'primary',
					type: 'screen printing',
				},
			});
		});
		return transaction;
	}

	findSecondary() {
		const transaction = this.prisma.$transaction(async (tx) => {
			this.logger.log({ level: 'info', message: 'Returning all secondary matrices', refCode: '41202' });
			return tx.pricingmatrix.findMany({
				where: {
					tableName: 'secondary',
					type: 'screen printing',
				},
			});
		});
		return transaction;
	}

	findAllSecondary(page = 1, take = 100, sortBy: string, sortOrder: string, search: string = '') {
		const transaction = this.prisma.$transaction(async (tx) => {
			const skip = (page - 1) * take; // Calculate the number of records to skip based on the page number
			this.logger.log({ level: 'info', message: `Returning all primary matrices with pagination, page: ${page}, take: ${take}, sortBy: ${sortBy}, sortOrder: ${sortOrder}, search: ${search}`, refCode: '41202' });

			return tx.pricingmatrix.findManyAndCount({
				skip: skip,
				take: take,
				orderBy: {
					[sortBy]: sortOrder,
				},
				where: {
					tableName: 'secondary',
					type: 'screen printing',
				},
			});
		});
		return transaction;
	}

	findTertiary() {
		const transaction = this.prisma.$transaction(async (tx) => {
			this.logger.log({ level: 'info', message: 'Returning all tertiary matrices', refCode: '41202' });
			return tx.pricingmatrix.findMany({
				where: {
					tableName: 'tertiary',
					type: 'screen printing',
				},
			});
		});
		return transaction;
	}

	findAllTertiary(page = 1, take = 100, sortBy: string, sortOrder: string, search: string = '') {
		const transaction = this.prisma.$transaction(async (tx) => {
			const skip = (page - 1) * take; // Calculate the number of records to skip based on the page number
			this.logger.log({ level: 'info', message: `Returning all primary matrices with pagination, page: ${page}, take: ${take}, sortBy: ${sortBy}, sortOrder: ${sortOrder}, search: ${search}`, refCode: '41202' });

			return tx.pricingmatrix.findManyAndCount({
				skip: skip,
				take: take,
				orderBy: {
					[sortBy]: sortOrder,
				},
				where: {
					tableName: 'tertiary',
					type: 'screen printing',
				},
			});
		});
		return transaction;
	}

	updateMatrix(id: number, updateMatrixDto: UpdateMatrixDto) {
		const transaction = this.prisma.$transaction(async (tx) => {
			this.logger.log({ level: 'info', message: `Updating one matrix ${id} with ${updateMatrixDto}`, refCode: '41203' });
			return tx.pricingmatrix.update({ where: { id: id }, data: updateMatrixDto });
		});
		return transaction;
	}

	// takes updateMatrixDtos with id
	updateManyMatrices(list: { id: number; data: UpdateMatrixDto }[]) {
		var successArray: Promise<any>[] = [];
		list.forEach((element) => {
			this.logger.log({ level: 'info', message: `Updating matrix ${element.id} with data: ${JSON.stringify(element.data)}`, refCode: '41203' });
			const transaction = this.prisma.$transaction(async (tx) => {
				return tx.pricingmatrix.update({
					where: { id: element.id },
					data: element.data,
				});
			});
			successArray.push(transaction);
		});
		return successArray;
	}

	deleteMatrix(id: number) {
		const transaction = this.prisma.$transaction(async (tx) => {
			this.logger.log({ level: 'info', message: `Deleting matrix ${id}`, refCode: '41204' });
			return tx.pricingmatrix.delete({ where: { id: id } });
		});
		return transaction;
	}

	deleteManyMatrices(ids: number[]) {
		console.log(ids);
		const transaction = this.prisma.$transaction(async (tx) => {
			this.logger.log({ level: 'info', message: `Deleting many matrices with ids ${ids}`, refCode: '41204' });
			return tx.pricingmatrix.deleteMany({ where: { id: { in: ids } } });
		});
		return transaction;
	}
}
