import { Topping, Pizza, ChangePizzaDto, Maybe } from "../generated/graphql";
import { PizzaList } from "../data-source/pizza.data-source";
import { v4 as uuidv4 } from 'uuid';
import { ToppingResolver } from "./topping-resolver";
import { PubSub } from "apollo-server";
import { PrismaClient } from "@prisma/client";


export const PIZZA_EVENTS = {
    PIZZA_CHANGED: "pizzaChanged",
}    
export class PizzaResolver {

    public pizzaEvent = new PubSub();
    private client: PrismaClient;
 

    constructor(client: PrismaClient) {
        this.client = client;
    }

    getById = (id: string): Pizza => {
        return PizzaList.filter(pizza => pizza.id === id)[0];
    };

    delete = (id: string): Pizza => {
        const index = PizzaList.indexOf(this.getById(id));
        if ( index ) {
            PizzaList.splice(index, 1)
        }
        return this.getById(id)
    };


    list = async (): Promise<Pizza[]> => {
        const res = await this.client.pizza.findMany();
        return res.map((pizza) => ({
            id: pizza.id,
            name: pizza.name,
            toppings: []
        } as Pizza))
    };

    getByName = (name: string): Pizza => {
        return PizzaList.filter(pizza => pizza.name === name)[0];
    };

    create = (pizzaCreateDto: ChangePizzaDto): Pizza => {
        this.client.topping.create({data: {}})
        // Get Topping Objects by Ids
        const toppings: Topping[] = pizzaCreateDto.toppingIds
            .map<string>((toppingId) => toppingId as string)
            .map<Topping>((toppingId) => ToppingResolver.getById(toppingId));
        // Init new Pizza Object
        const pizza: Pizza = {
            id: uuidv4(),
            name: pizzaCreateDto.name,
            toppings: toppings
        }
        // Add Pizza to 'Database'
        PizzaList.push(pizza);
        this.pizzaEvent.publish(PIZZA_EVENTS.PIZZA_CHANGED, {
            pizzasChanged: PizzaList
        });
        console.log(`Create Pizza ...`, pizza)
        return pizza;
    };

    update = (pizzaId: string, pizzaUpdateDto: ChangePizzaDto): Pizza => {
        const pizza = this.getById(pizzaId);
        if (!pizza) {
            throw new Error(
                `No Pizza found with id ${pizzaId}`
            )
        }
        const toppings: Topping[] = pizzaUpdateDto.toppingIds
            .map<string>((toppingId: Maybe<string>) => toppingId as string)
            .map<Topping>((toppingId: string) => ToppingResolver.getById(toppingId));
        pizza.name = pizzaUpdateDto.name;
        pizza.toppings = toppings;
        const pizzaIndex = PizzaList.indexOf(pizza);
        PizzaList[pizzaIndex] = pizza;
        console.log(`Update Pizza ...`, pizza)
        this.pizzaEvent.publish(PIZZA_EVENTS.PIZZA_CHANGED, {
            pizzasChanged: PizzaList
        });
        return pizza;
    };

}