import graphqlFields from 'graphql-fields';
import { Resolver, Query, Args, ID, Info, Mutation } from '@nestjs/graphql';
import { Types } from 'mongoose';
import { Build } from '@/models/build.model';
import { CreateBuildInput } from './dto/create-build.input';
import { UpdateBuildResponsibleInput, UpdateBuildAttributeInput, UpdateBuildInput } from './dto/update-build.input';
import { BuildService } from './build.service';
import { ListArguments } from '@/dto/list.input';
import { ListBuildResponse, ListPartialAreaResponse, ListPartialCompanyResponse, ListPartialIbanResponse } from './dto/list-build.response';
import type { GraphQLResolveInfo } from 'graphql';

@Resolver()
export class BuildResolver {

    constructor(private readonly buildService: BuildService) { }

    @Query(() => ListBuildResponse, { name: 'builds' })
    async getBuilds(@Info() info: GraphQLResolveInfo, @Args('input') input: ListArguments): Promise<ListBuildResponse> {
        const fields = graphqlFields(info); const projection = this.buildService.buildProjection(fields); return this.buildService.findAll(input.skip, input.limit, input.sort, input.filters);
    }

    @Query(() => ListPartialAreaResponse, { name: 'getBuildsAreas' })
    async getBuildsAreas(@Info() info: GraphQLResolveInfo, @Args('id') id: string, @Args('input') input: ListArguments): Promise<ListPartialAreaResponse> {
        const fields = graphqlFields(info); const projection = this.buildService.buildProjection(fields); return this.buildService.findAllAreas(id, input.skip, input.limit, input.sort, input.filters);
    }

    @Query(() => ListPartialIbanResponse, { name: 'getBuildsIbans' })
    async getBuildsIbans(@Info() info: GraphQLResolveInfo, @Args('id') id: string, @Args('input') input: ListArguments): Promise<ListPartialIbanResponse> {
        const fields = graphqlFields(info); const projection = this.buildService.buildProjection(fields); return this.buildService.findAllIbans(id, input.skip, input.limit, input.sort, input.filters);
    }

    @Query(() => ListPartialCompanyResponse, { name: 'getBuildsCompaniesAndResponsibles' })
    async getBuildsCompaniesAndResponsibles(@Info() info: GraphQLResolveInfo, @Args('id') id: string, @Args('input') input: ListArguments): Promise<ListPartialCompanyResponse> {
        const fields = graphqlFields(info); const projection = this.buildService.buildProjection(fields); return this.buildService.findAllCompaniesAndResponsibles(id, input.skip, input.limit, input.sort, input.filters);
    }

    @Query(() => Build, { name: 'build', nullable: true })
    async getBuild(@Args('id', { type: () => ID }) id: string, @Info() info: GraphQLResolveInfo): Promise<Build | null> {
        const fields = graphqlFields(info); const projection = this.buildService.buildProjection(fields); return this.buildService.findById(new Types.ObjectId(id), projection);
    }

    @Mutation(() => Boolean, { name: 'deleteBuild' })
    async deleteBuild(@Args('uuid') uuid: string): Promise<boolean> { return this.buildService.delete(uuid) }

    @Mutation(() => Build, { name: 'createBuild' })
    async createBuild(@Args('input') input: CreateBuildInput): Promise<Build> { return this.buildService.create(input) }

    @Mutation(() => Build, { name: 'updateBuild' })
    async updateBuild(@Args('uuid') uuid: string, @Args('input') input: UpdateBuildInput): Promise<Build> { return this.buildService.update(uuid, input) }

    @Mutation(() => Build, { name: 'updateBuildResponsible' })
    async updateBuildResponsible(@Args('uuid') uuid: string, @Args('input') input: UpdateBuildResponsibleInput): Promise<Build> { return this.buildService.updateResponsible(uuid, input) }

    @Mutation(() => Build, { name: 'updateBuildAttribute' })
    async updateBuildAttribute(@Args('uuid') uuid: string, @Args('input') input: UpdateBuildAttributeInput): Promise<Build> { return this.buildService.updateAttribute(uuid, input) }

}
