import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { IFullUser } from 'src/modules/users/users.interface';
import { ImageHistory } from './model/image-history.model';
import { StorageService } from '../storage/storage.service';
import QueryBuilder from 'src/common/builder/QueryBuilder';

@Injectable()
export class ImageHistoryService {

	constructor(
		@InjectModel(ImageHistory.name) private readonly imageHistoryModel: Model<ImageHistory>,
		private readonly storageService: StorageService
	) { }

	// gets all generated images by user
	async findAllImageByUser(user: IFullUser, query: Record<string, any>) {
		// if(user?.subscription?.plan === 'free') {
		// 	throw new BadRequestException('You need to upgrade to a premium plan to access this feature');
		// }

		const page = query['page'] ? parseInt(query['page']) : 1;
		const limit = query['limit'] ? parseInt(query['limit']) : 10;
		const skip = (page - 1) * limit;

		// const imageHistoryQuery = new QueryBuilder(
		// 	this.imageHistoryModel.find({ user: user._id }),
		// 	query)
		// 	.filter()
		// 	.sort()
		// 	.paginate()
		// 	.fields();

		// const imageHistory = await imageHistoryQuery.modelQuery;

		const imageHistoryQuery = await this.imageHistoryModel.aggregate([
			{
				$match: {
					user: user._id
				}
			},
			{
				$sort: {
					createdAt: -1
				}
			},
			{
				$project: {
					_id: 1,
					images: 1,
					prompt: 1,
					createdAt: 1
				}
			},
			{
				$facet: {
					metadata: [{ $count: "total" }],
					data: [
						{ $skip: skip },
						{ $limit: limit }
					]
				}
			}
		])

		const metadata = {
			...imageHistoryQuery?.[0]?.metadata?.[0],
			page,
			limit,
			skip,
			totalPages: Math.ceil(imageHistoryQuery?.[0]?.metadata?.[0]?.total / limit),
			hasMorePages: (page * limit) < imageHistoryQuery?.[0]?.metadata?.[0]?.total,
			previousPage: page > 1 ? page - 1 : null,
			nextPage: (page * limit) < imageHistoryQuery?.[0]?.metadata?.[0]?.total ? page + 1 : null
		}

		const imageHistory = imageHistoryQuery?.[0]?.data;

		const purseImages = []

		imageHistory?.forEach((image: any) => {
			image.images?.forEach((img: any) => {
				if (img?.id) {
					img.url = `https://cdn.binaplus.co.il/${img.url.split('/').pop()}`
					purseImages.push({
						...img,
						prompt: image.prompt,
						imageHistoryId: image._id,
					})
				}
			});
		});



		return {
			meta: metadata,
			data: purseImages
		}
	}


	async findAllImagesForAdmin(query: Record<string, any>) {
		const dataQuery = new QueryBuilder(
			this.imageHistoryModel.find({
				// images length: { $gt: 0 } // ensure there are images
				images: { $exists: true, $ne: [] } // ensure there are images
			}).select('images prompt finalPrompt user  model createdAt updatedAt filterResult'),
			query)
			.search(['prompt'])
			.filter()
			.sort()
			.paginate()
			.fields();

		const dataQueryPromise = dataQuery.modelQuery;

		const metaQuery = dataQuery.getMeta();

		const [data, meta] = await Promise.all([dataQueryPromise, metaQuery]);

		// format the images. images should be split into individual objects with their respective prompts and imageHistoryId
		const purseImages = []

		const jsonData = (data as any)?.map((item: any) => item?.toJSON() || item);

		jsonData?.forEach((image: any) => {

			const { images, ...rest } = image;

			image?.images?.forEach((img: any) => {
				if (img?.id) {
					purseImages.push(
						{
							...rest,
							image: img?.url
						}
					)
				}
			});
		});

		return {
			data: purseImages,
			meta
		}
	}

	// gets a single image by id
	async findImageById(user: IFullUser, id: string) {
		const image = await this.imageHistoryModel.findOne({
			_id: id,
			user: user._id,
		});

		if (!image) {
			throw new NotFoundException('Image not found');
		}

		return image;
	}


	async deleteImageById(user: IFullUser, imageHistoryId: string, imageId: string) {

		const image = await this.imageHistoryModel.findOne({
			_id: imageHistoryId,
			user: user._id,
			"images.id": imageId
		});

		if (!image) {
			throw new NotFoundException('Image not found');
		}

		// delete document if no image is left (empty array or only one image)
		if (image?.images?.length <= 1) {
			await this.imageHistoryModel.deleteOne({ _id: imageHistoryId });
		} else {
			// pull image from array
			await this.imageHistoryModel.updateOne(
				{ _id: imageHistoryId },
				{ $pull: { images: { id: imageId } } }
			);
		}



		// delete image from google cloud storage
		await this.storageService.deleteFile(imageId, user);
		return null

	}

}
