import { z } from "zod";
import {
  adminProcedure,
  createTRPCRouter,
  protectedProcedure,
  publicProcedure,
} from "~/server/api/trpc";
import {
  zAnnuncioId,
  zOrdineId,
  zPagamentoId,
  zServizioId,
  zUserId,
} from "~/server/utils/zod_types";
import type { NewServizio, ServizioUpdate } from "~/schemas/public/Servizio";
import {
  addServizio,
  getServiziByUserId,
  updateServizio,
  deleteServizio,
  getDataPerAcquisto,
  postAcquistoDataHandler,
  getAllServizioAnnunci,
  addServizioAnnunci,
  getAnnunciAvailableToAdd,
  deleteServizioAnnuncio,
  SbloccaContatti,
  interruzioneServizio,
  getServizioById,
  InteractionLogicTipologia,
  sendServizioEmail,
  userConfirmImmobile,
  updateServizioAnnuncio,
  getServizioAnnuncio,
  getServizioPagamentoData,
  getUserPagamenti,
  getAllPagamenti,
  SendContactEmail,
  setupSaldoServizio,
  updatePagamento,
  removePagamento,
  getCompatibileAnnunci,
  getPreOnboardData,
  getOrdineRicevutaData,
  isOrdineAwaitingPayment,
  setupSaldoConsulenzaServizio,
} from "~/server/controllers/servizio.controller";
import type { Users } from "~/schemas/public/Users";
import { type UsersAnagraficaUpdate } from "~/schemas/public/UsersAnagrafica";
import type { ServizioAnnunciUpdate } from "~/schemas/public/ServizioAnnunci";
import type { PaymentsUpdate } from "~/schemas/public/Payments";
import {
  getOrdineById,
  getOrdini,
  removeOrder,
  updateOrder,
} from "~/server/controllers/ordini.controller";
import type { OrdiniUpdate } from "~/schemas/public/Ordini";

export const servizioRouter = createTRPCRouter({
  getServizio: protectedProcedure
    .input(
      z.object({
        servizioId: zServizioId,
      }),
    )
    .query(async ({ input }) => {
      return await getServizioById(input.servizioId);
    }),
  addServizio: adminProcedure
    .input(
      z.object({
        data: z.custom<NewServizio>(),
      }),
    )
    .mutation(async ({ input }) => {
      return await addServizio(input.data);
    }),
  updateServizio: protectedProcedure
    .input(
      z.object({
        servizioId: zServizioId,
        data: z.custom<ServizioUpdate>(),
      }),
    )
    .mutation(async ({ input }) => {
      return await updateServizio({
        servizioId: input.servizioId,
        data: input.data,
      });
    }),
  deleteServizio: adminProcedure
    .input(
      z.object({
        servizioId: zServizioId,
      }),
    )
    .mutation(async ({ input }) => {
      return await deleteServizio(input.servizioId);
    }),

  getUserServizi: adminProcedure
    .input(
      z.object({
        userId: zUserId,
      }),
    )
    .query(async ({ input }) => {
      return await getServiziByUserId(input.userId);
    }),
  getPreOnboardData: publicProcedure
    .input(
      z.object({
        servizioId: zServizioId,
      }),
    )
    .query(async ({ input }) => {
      return await getPreOnboardData(input.servizioId);
    }),

  getAcquistoData: protectedProcedure
    .input(
      z.object({
        servizioId: zServizioId,
      }),
    )
    .query(async ({ input }) => {
      return await getDataPerAcquisto(input.servizioId);
    }),

  postAcquistoData: protectedProcedure
    .input(
      z.object({
        servizioId: zServizioId,
        userId: zUserId,
        user: z.custom<
          Pick<Users, "nome" | "cognome" | "email" | "telefono" | "username">
        >(),
        anagrafica: z.custom<UsersAnagraficaUpdate>(),
        servizio: z.custom<ServizioUpdate>(),
        skipOrdine: z.boolean().optional(),
      }),
    )
    .mutation(async ({ input }) => {
      return await postAcquistoDataHandler({
        ...input,
      });
    }),
  getAllServizioAnnunci: protectedProcedure
    .input(
      z.object({
        userId: zUserId,
      }),
    )
    .query(async ({ input }) => {
      return await getAllServizioAnnunci(input.userId);
    }),
  getServizioAnnuncio: protectedProcedure
    .input(
      z.object({
        servizioId: zServizioId,
        annuncioId: zAnnuncioId,
      }),
    )
    .query(async ({ input }) => {
      return await getServizioAnnuncio({
        servizioId: input.servizioId,
        annuncioId: input.annuncioId,
      });
    }),
  addServizioAnnunci: adminProcedure
    .input(
      z.object({
        annunci: z.array(zAnnuncioId),
        servizioId: zServizioId,
      }),
    )
    .mutation(async ({ input }) => {
      return await addServizioAnnunci({
        annunci: input.annunci,
        servizioId: input.servizioId,
      });
    }),
  updateServizioAnnunci: protectedProcedure
    .input(
      z.object({
        servizioId: zServizioId,
        annuncioId: zAnnuncioId,
        data: z.custom<ServizioAnnunciUpdate>(),
      }),
    )
    .mutation(async ({ input }) => {
      return await updateServizioAnnuncio({
        servizioId: input.servizioId,
        annuncioId: input.annuncioId,
        data: input.data,
      });
    }),
  getAnnunciAvailableToAdd: adminProcedure
    .input(
      z.object({
        servizioId: zServizioId,
      }),
    )
    .query(async ({ input }) => {
      return await getAnnunciAvailableToAdd(input.servizioId);
    }),
  removeAnnuncioServizio: protectedProcedure
    .input(
      z.object({
        servizioId: zServizioId,
        annuncioId: zAnnuncioId,
      }),
    )
    .mutation(async ({ input }) => {
      return await deleteServizioAnnuncio(input.servizioId, input.annuncioId);
    }),

  unlockServizioContatti: protectedProcedure
    .input(
      z.object({
        servizioId: zServizioId,
        annuncioId: zAnnuncioId,
      }),
    )
    .mutation(async ({ input }) => {
      return await SbloccaContatti({
        servizioId: input.servizioId,
        annuncioId: input.annuncioId,
      });
    }),
  interruzioneServizio: protectedProcedure
    .input(
      z.object({
        servizioId: zServizioId,
      }),
    )
    .mutation(async ({ input }) => {
      return await interruzioneServizio(input.servizioId);
    }),
  AnnuncioServizioTipologiaMatch: protectedProcedure
    .input(
      z.object({
        userId: zUserId,
        tipologia: z.string(),
        annuncioId: zAnnuncioId,
      }),
    )
    .query(async ({ input }) => {
      return await InteractionLogicTipologia({
        userId: input.userId,
        tipologia: input.tipologia,
        annuncioId: input.annuncioId,
      });
    }),
  sendServizioEmail: protectedProcedure
    .input(
      z.object({
        servizioId: zServizioId,
        userId: zUserId,
      }),
    )
    .mutation(async ({ input }) => {
      return await sendServizioEmail({
        servizioId: input.servizioId,
        userId: input.userId,
      });
    }),
  userConfirmImmobile: protectedProcedure
    .input(
      z.object({
        servizioId: zServizioId,
        annuncioId: zAnnuncioId,
      }),
    )
    .mutation(async ({ input }) => {
      return await userConfirmImmobile({
        servizioId: input.servizioId,
        annuncioId: input.annuncioId,
      });
    }),
  isOrdineAwaitingPayment: protectedProcedure
    .input(
      z.object({
        ordineId: zOrdineId,
      }),
    )
    .query(async ({ input }) => {
      return await isOrdineAwaitingPayment(input.ordineId);
    }),
  getServizioPaymentData: protectedProcedure
    .input(
      z.object({
        ordineId: zOrdineId,
      }),
    )
    .query(async ({ input }) => {
      return await getServizioPagamentoData(input.ordineId);
    }),
  getAllPagamenti: adminProcedure.query(async () => {
    return await getAllPagamenti();
  }),
  updatePagamento: adminProcedure
    .input(
      z.object({
        pagamentoId: zPagamentoId,
        data: z.custom<PaymentsUpdate>(),
      }),
    )
    .mutation(async ({ input }) => {
      return await updatePagamento({
        paymentId: input.pagamentoId,
        data: input.data,
      });
    }),
  removePagamento: adminProcedure
    .input(
      z.object({
        pagamentoId: zPagamentoId,
      }),
    )
    .mutation(async ({ input }) => {
      return await removePagamento(input.pagamentoId);
    }),
  getUserPagamenti: protectedProcedure
    .input(
      z.object({
        userId: zUserId,
      }),
    )
    .query(async ({ input }) => {
      return await getUserPagamenti(input.userId);
    }),

  sendContattoEmail: publicProcedure
    .input(
      z.object({
        nome: z.string(),
        email: z.string(),
        telefono: z.string(),
        messaggio: z.string(),
        codice: z.string(),
      }),
    )
    .mutation(async ({ input }) => {
      return await SendContactEmail({
        ...input,
      });
    }),
  setupSaldoServizio: protectedProcedure
    .input(
      z.object({
        servizioId: zServizioId,
        annuncioId: zAnnuncioId,
      }),
    )
    .mutation(async ({ input }) => {
      return await setupSaldoServizio({
        servizioId: input.servizioId,
        annuncioId: input.annuncioId,
      });
    }),
  setupSaldoConsulenzaServizio: protectedProcedure
    .input(
      z.object({
        servizioId: zServizioId,
        annuncioId: zAnnuncioId,
      }),
    )
    .mutation(async ({ input }) => {
      return await setupSaldoConsulenzaServizio({
        servizioId: input.servizioId,
        annuncioId: input.annuncioId,
      });
    }),

  getCompatibileAnnunci: protectedProcedure
    .input(
      z.object({
        servizioId: zServizioId,
      }),
    )
    .query(async ({ input }) => {
      return await getCompatibileAnnunci(input.servizioId);
    }),
  getOrdini: protectedProcedure
    .input(
      z.object({
        userId: zUserId.optional(),
      }),
    )
    .query(async ({ input }) => {
      return await getOrdini(input.userId);
    }),
  getOrdineById: protectedProcedure
    .input(
      z.object({
        ordineId: zOrdineId,
      }),
    )
    .query(async ({ input }) => {
      return await getOrdineById(input.ordineId);
    }),
  removeOrder: adminProcedure
    .input(
      z.object({
        ordineId: zOrdineId,
      }),
    )
    .mutation(async ({ input }) => {
      return await removeOrder(input.ordineId);
    }),

  updateOrder: adminProcedure
    .input(
      z.object({
        ordineId: zOrdineId,
        data: z.custom<OrdiniUpdate>(),
      }),
    )
    .mutation(async ({ input }) => {
      return await updateOrder({
        ordineId: input.ordineId,
        data: input.data,
      });
    }),
  getOrdineRicevutaData: protectedProcedure
    .input(
      z.object({
        ordineId: zOrdineId,
      }),
    )
    .query(async ({ input, ctx }) => {
      return await getOrdineRicevutaData({ ordineId: input.ordineId, ctx });
    }),
});
