import { createContext, useContext } from "react";
import toast from "react-hot-toast";
import type { AnnunciId } from "~/schemas/public/Annunci";
import type { ServizioServizioId } from "~/schemas/public/Servizio";
import type { ServizioAnnunciUpdate } from "~/schemas/public/ServizioAnnunci";
import type { UsersId } from "~/schemas/public/Users";
import type { ServizioData } from "~/server/controllers/servizio.controller";
import { api } from "~/utils/api";

type ServizioProviderProps = {
	isAdmin: boolean;
	userId: UsersId;
	servizioId: ServizioServizioId;
	servizio: ServizioData;
	children: React.ReactNode;
};
type ServizioContextProps = {
	isAdmin: boolean;
	userId: UsersId;
	servizioId: ServizioServizioId;
	servizio: ServizioData;
};

const ServizioContext = createContext<ServizioContextProps | null>(null);

export const ServizioProvider = ({
	children,
	...props
}: ServizioProviderProps) => {
	return (
		<ServizioContext.Provider value={{ ...props }}>
			{children}
		</ServizioContext.Provider>
	);
};

export const useServizio = () => {
	const servizioContext = useContext(ServizioContext);
	if (!servizioContext) {
		throw new Error("useServizio must be used within a ServizioProvider");
	}
	return servizioContext;
};

type ServizioAnnuncioProviderProps = {
	data: ServizioData["annunci"][number];
	servizioId: ServizioServizioId;
	userId: UsersId;
	children: React.ReactNode;
};

type ServizioAnnuncioContextProps = {
	data: ServizioData["annunci"][number];
	annuncioId: AnnunciId;
	updateServizioAnnunci: (data: ServizioAnnunciUpdate) => Promise<void>;
};

const ServizioAnnuncioContext =
	createContext<ServizioAnnuncioContextProps | null>(null);
export const ServizioAnnuncioProvider = ({
	data,
	servizioId,
	userId,
	children,
}: ServizioAnnuncioProviderProps) => {
	const utils = api.useUtils();
	const { mutateAsync } = api.servizio.updateServizioAnnunci.useMutation({
		onError: (error) => {
			toast.error(error.message);
		},
		onSuccess: async () => {
			await utils.servizio.getAllServizioAnnunci.invalidate({
				userId: userId,
			});
			await utils.servizio.getServizio.invalidate({
				servizioId,
			});

			toast.success("Dati salvati con successo");
		},
	});
	const updateServizioAnnunci = async (upd: ServizioAnnunciUpdate) => {
		await mutateAsync({
			annuncioId: data.id,
			servizioId,
			data: upd,
		});
	};

	return (
		<ServizioAnnuncioContext.Provider
			value={{ annuncioId: data.annunci_id, data, updateServizioAnnunci }}
		>
			{children}
		</ServizioAnnuncioContext.Provider>
	);
};

export const useServizioAnnuncio = () => {
	const servizioAnnuncioContext = useContext(ServizioAnnuncioContext);
	if (!servizioAnnuncioContext) {
		throw new Error(
			"useServizioAnnuncio must be used within a ServizioAnnuncioProvider",
		);
	}
	return servizioAnnuncioContext;
};
