import {
	Context,
	Parent,
	Query,
	ResolveField,
	Resolver,
	Subscription,
} from '@nestjs/graphql';
import { AgentModel } from './models/agent.model';
import { PrismaService } from '../prisma/prisma.service';
import { Inject, UseGuards } from '@nestjs/common';
import { AuthGuard } from '../auth/auth.guard';
import { Request } from 'express';
import { EntryModel } from './models/entry.model';
import { EntryService } from '../utils/entry.service';
import { PubSub } from 'graphql-subscriptions';

@Resolver(() => AgentModel)
export class AgentResolver {
	constructor(
		@Inject('PUBSUB')
		private readonly pubSub: PubSub,
		private readonly prisma: PrismaService,
		private readonly entryService: EntryService,
	) {}

	@Subscription(() => AgentModel, {
		resolve: (payload) => {
			payload.slug = null;
		},
	})
	onAgentUpdate() {
		return this.pubSub.asyncIterator('onAgentUpdate');
	}

	@Query(() => [AgentModel])
	@UseGuards(AuthGuard)
	async getAgents(): Promise<AgentModel[]> {
		return await this.prisma.agent.findMany({
			select: {
				id: true,
				name: true,
				avatar: true,
				bio: true,
				flags: true,
			},
		});
	}

	@ResolveField('entries')
	async entries(
		@Context() { req }: { req: Request },
		@Parent() parent: AgentModel,
	): Promise<EntryModel[]> {
		if (req.group)
			return this.entryService.getAccessibleEntries(
				req.group.id,
				parent.id,
			);
		else
			return this.prisma.entry
				.findMany()
				.then((entries) =>
					entries.map(this.entryService.unlockedEntry),
				);
	}

	@ResolveField('value')
	async value(@Parent() parent: AgentModel): Promise<number> {
		const codes = await this.prisma.tokenCode.findMany({
			where: { agentId: parent.id },
			select: { value: true },
		});

		return codes.reduce((prev, curr) => prev + curr.value, 0);
	}
}