import { Injectable, Logger } from '@nestjs/common';
import { CreateClientDto } from './dto/create-client.dto';
import { UpdateClientDto } from './dto/update-client.dto';
import { PrismaService } from 'src/prisma/prisma.service';

@Injectable()
export class ClientsService {
	constructor(private prisma: PrismaService) {}
	private readonly logger = new Logger(ClientsService.name);
	create(createClientDto: CreateClientDto) {
		const transaction = this.prisma.$transaction(async (tx) => {
			this.logger.log({ level: 'info', message: `Client created ${createClientDto}`, refCode: '22201' });
			return tx.client.create({ data: createClientDto });
		});
		return transaction;
	}

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

			if (take < 0) {
				take = 100;
			}
			let searchID = parseInt(search);

			if (Number.isNaN(searchID)) {
				searchID = 0;
			}

			// Default Query
			let query = {
				skip,
				take,
				orderBy: {
					[sortBy]: sortOrder,
				},
                where: {
                    id: {
                        not: 1, // Exclude the _System client
                    }
                },
			} as any;

			// Search by ID
			if (search) {
				query.where.OR = [{ id: { equals: searchID } }, { name: { contains: search } }, { notes: { contains: search } }, { address2: { contains: search } }, { state: { contains: search } }];
			}
			return tx.client.findManyAndCount(query);
		});
		return transaction;
	}

	findOne(id: number) {
		const transaction = this.prisma.$transaction(async (tx) => {
			// this.logger.log({ level: 'info', message: `Returning one client ${id}`, refCode: '22202' });
			return tx.client.findUnique({
				where: { id },
				include: {
					users: {
						select: {
							id: true,
							name: true,
							email: true,
							role: true,
                            favourite: true,
                            phone: true,
                            address1: true,
                            address2: true,
                            city: true,
                            state: true,
                            postcode: true,
                            country: true,
						},
                        where: {
                            active: true,
                        },
                        orderBy: {
                            favourite: 'desc',
                        },
					},
					jobs: true,
				},
			});
		});
		return transaction;
	}

	findOneSimple(id: number) {
		const transaction = this.prisma.$transaction(async (tx) => {
			// this.logger.log({ level: 'info', message: `Returning one client ${id} simply`, refCode: '22202' });
			return tx.client.findUnique({
				where: { id },
				select: {
					id: true,
					name: true,
				},
			});
		});
		return transaction;
	}

	findAllSimple() {
		const transaction = this.prisma.$transaction(async (tx) => {
			// this.logger.log({ level: 'info', message: `Returning all clients`, refCode: '22202' });
			return tx.client.findMany({
				select: {
					id: true,
					name: true,
				},
                where: {
                    id: {
                        not: 1, // Exclude the _System client
                    }
                },
			});
		});
		return transaction;
	}

	update(id: number, updateClientDto: UpdateClientDto) {
		const transaction = this.prisma.$transaction(async (tx) => {
			this.logger.log({ level: 'info', message: `Update one client ${id} with ${updateClientDto}`, refCode: '22203' });
			return tx.client.update({ where: { id }, data: updateClientDto });
		});
		return transaction;
	}

	remove(id: number) {
        if(id === 1) {
            this.logger.error({ level: 'error', message: `Attempted to remove the _System client ${id}`, refCode: '22204' });
            throw new Error('Cannot remove the _System client');
        } 

		const transaction = this.prisma.$transaction(async (tx) => {
			this.logger.log({ level: 'info', message: `Removing one client ${id}`, refCode: '22204' });
			return tx.client.delete({ where: { id } });
		});
		return transaction;
	}
}
