import { Injectable, Logger } from '@nestjs/common';
import { CreateInkDto } from './dto/create-ink.dto';
import { UpdateInkDto } from './dto/update-ink.dto';
import { PrismaService } from 'src/prisma/prisma.service';
import { EmailsService } from 'src/emails/emails.service';
import { ColorLibraries } from 'utils/colors';

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

	create(createInkDto: CreateInkDto) {
		const transaction = this.prisma.$transaction(async (tx) => {
			this.logger.log({ level: 'info', message: `Ink created with ${createInkDto}`, refCode: '36201' });
			return tx.ink.create({ data: createInkDto });
		});
		return transaction;
	}

	findAll(skip = 0, take = 10, sortBy: string = 'name', sortOrder: string = 'asc', search: string = '') {
		const transaction = this.prisma.$transaction(async (tx) => {
            // this.logger.log({ level: 'info', message: 'Returning all inks', refCode: '36202' });
			if (take < 0) {
				take = 100;
			}

			// Default Query
			let query = {
				skip,
				take,
				orderBy: {
					[sortBy]: sortOrder,
				},
                where: {
                    active: true,
                }
			} as any;

			if (search) {
				query.where.OR = [
                    { 
                        color: { contains: search } 
                    }, 
                    { 
                        name: { contains: search } 
                    }, 
                    { 
                        storageCode: { contains: search } 
                    }
                ];
			}

			return tx.ink.findManyAndCount(query);
		});
		return transaction;
	}
    

	findOne(id: number) {
		const transaction = this.prisma.$transaction(async (tx) => {
			// this.logger.log({ level: 'info', message: `Returning one ink ${id}`, refCode: '36202' });
			return tx.ink.findUnique({ where: { id } });
		});
		return transaction;
	}

	update(id: number, updateInkDto: UpdateInkDto) {
		const transaction = this.prisma.$transaction(async (tx) => {
			this.logger.log({ level: 'info', message: `Updating one ink ${id} with ${updateInkDto}`, refCode: '36203' });
			return tx.ink.update({
				where: { id },
				data: updateInkDto,
			});
		});
		return transaction;
	}

	remove(id: number) {
		const transaction = this.prisma.$transaction(async (tx) => {
			this.logger.log({ level: 'info', message: `Deleting one ink ${id}`, refCode: '36204' });
			// return tx.ink.delete({ where: { id } });
            return tx.ink.update({
                where: { id },
                data: { active: false },
            });
		});
		return transaction;
	}

    async importLibrary(library: string) {
       
        const transaction = await this.prisma.$transaction(async (tx) => {
            let colorsToImport: CreateInkDto[] = [];

            const libraryExistsOnTable = await tx.ink.findFirst({ where: { library: library } });

            /* If doesn't exist import to database */
            if (!libraryExistsOnTable) {

                // Get the library data from ColorLibraries
                const targetLibrary = ColorLibraries.find((lib) => lib.name === library);
                const libraryTitle = targetLibrary ? targetLibrary.title : library;
                const libraryColors = targetLibrary ? targetLibrary.colors : [];

                if (libraryColors.length > 0) {
                    colorsToImport = libraryColors.map((color) => {
                        return {
                            name: color.name,
                            color: color.color,
                            library: libraryTitle,
                            storageCode: '',
                            active: true,
                        };
                    });
                }

                return tx.ink.createMany({ data: colorsToImport, skipDuplicates: true });

            /* If exists, change the 'active' status to true */
            } else {
                return tx.ink.updateMany({
                    where: { 
                        library: library, 
                        active: false 
                    },
                    data: { active: true },
                });
            }
        });

        return transaction;
	}

    async removeLibrary(library: string) {
        const transaction = await this.prisma.$transaction(async (tx) => {
            const libraryExistsOnTable = await tx.ink.findFirst({ where: { library: library, active: true } });

            if (libraryExistsOnTable) {
                return tx.ink.updateMany({
                    where: { 
                        library: library, 
                        active: true 
                    },
                    data: { active: false },
                });
            } else {
                return { error: `The ${library} library hasn't been imported yet.` };
            }
        });

        return transaction;
	}
}
