import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Types, Model } from 'mongoose';
import { BuildArea, BuildAreaDocument } from '@/models/build-area.model';
import { CreateBuildAreaInput } from './dto/create-build-area.input';
import { ListBuildAreaResponse } from './dto/list-build-area.response';
import { UpdateBuildAreaInput } from './dto/update-build-area.input';
import { ListArguments } from '@/dto/list.input';
import { Build, BuildDocument } from '@/models/build.model';

@Injectable()
export class BuildAreaService {

    constructor(
        @InjectModel(BuildArea.name) private readonly buildAreaModel: Model<BuildAreaDocument>,
        @InjectModel(Build.name) private readonly buildModel: Model<BuildDocument>
    ) { }

    async findAll(projection: any, listArguments: ListArguments): Promise<ListBuildAreaResponse> {
        const { skip, limit, sort, filters } = listArguments;
        const query: any = {}; if (filters && Object.keys(filters).length > 0) { Object.assign(query, filters) };
        if (filters?.buildId) { query.buildId = new Types.ObjectId(filters?.buildId) };
        const totalCount = await this.buildAreaModel.countDocuments(query).exec();
        const data = await this.buildAreaModel.find(query, projection, { lean: true }).skip(skip).limit(limit).sort(sort).exec();
        return { data, totalCount };
    }

    async findById(id: Types.ObjectId, projection?: any): Promise<BuildAreaDocument | null> { return this.buildAreaModel.findById(id, projection, { lean: false }).populate({ path: 'buildArea', select: projection?.buildArea }).exec() }

    async create(input: CreateBuildAreaInput): Promise<BuildAreaDocument> {
        const getBuildID = await this.buildModel.findById(input?.buildId, { _id: 1 }, { lean: true }).exec();
        if (getBuildID) { input.buildId = new Types.ObjectId(getBuildID._id) };
        const buildArea = new this.buildAreaModel(input); return buildArea.save()
    }

    async update(uuid: string, input: UpdateBuildAreaInput): Promise<BuildAreaDocument> { const buildArea = await this.buildAreaModel.findOne({ uuid }); if (!buildArea) { throw new Error('BuildArea not found') }; buildArea.set(input); return buildArea.save() }

    async delete(uuid: string): Promise<boolean> { const buildArea = await this.buildAreaModel.deleteMany({ uuid }); return buildArea.deletedCount > 0 }

    buildProjection(fields: Record<string, any>): any {
        const projection: any = {};
        for (const key in fields) {
            if (key === 'buildArea' && typeof fields[key] === 'object') { for (const subField of Object.keys(fields[key])) { projection[`buildArea.${subField}`] = 1 } }
            else { projection[key] = 1 }
        }; return projection;
    }

}
