import type {
  NewPrezziario,
  Prezziario,
  PrezziarioIdprezziario,
  PrezziarioUpdate,
} from "~/schemas/public/Prezziario";
import { db, type Querier } from "~/server/db";
import { TRPCError } from "@trpc/server";
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";

export const getPrezziario = async () => {
  try {
    return await db
      .selectFrom("prezziario")
      .selectAll()
      .where("isActive", "=", true)
      .orderBy("prezzo_cent", "asc")
      .execute();
  } catch (error) {
    throw new TRPCError({
      code: "INTERNAL_SERVER_ERROR",
      message: "Error getting prezziario: " + (error as Error).message,
    });
  }
};

export const addPrezziario = async ({
  db,
  input,
}: {
  db: Querier;
  input: NewPrezziario;
}): Promise<Prezziario> => {
  try {
    return await db
      .insertInto("prezziario")
      .values(input)
      .returningAll()
      .executeTakeFirstOrThrow();
  } catch (error) {
    throw new TRPCError({
      code: "INTERNAL_SERVER_ERROR",
      message: "Error adding prezziario: " + (error as Error).message,
    });
  }
};
export const updatePrezziario = async ({
  db,
  prezziarioId,
  input,
}: {
  db: Querier;
  prezziarioId: PrezziarioIdprezziario;
  input: PrezziarioUpdate;
}): Promise<Prezziario> => {
  try {
    return await db
      .updateTable("prezziario")
      .set(input)
      .where("prezziario.idprezziario", "=", prezziarioId)
      .returningAll()
      .executeTakeFirstOrThrow();
  } catch (error) {
    throw new TRPCError({
      code: "INTERNAL_SERVER_ERROR",
      message: "Error updating prezziario: " + (error as Error).message,
    });
  }
};

export const deletePrezziario = async ({
  db,
  prezziarioId,
}: {
  db: Querier;

  prezziarioId: PrezziarioIdprezziario;
}): Promise<void> => {
  try {
    await db
      .deleteFrom("prezziario")
      .where("prezziario.idprezziario", "=", prezziarioId)
      .execute();
  } catch (error) {
    throw new TRPCError({
      code: "INTERNAL_SERVER_ERROR",
      message: "Error deleting prezziario: " + (error as Error).message,
    });
  }
};

type MinimalPrezziario = Pick<
  Prezziario,
  "idprezziario" | "prezzo_cent" | "nome_it" | "nome_en" | "sconto"
>;
type PrezziarioByTipologia = {
  acconto: MinimalPrezziario;
  saldi: MinimalPrezziario[];
};

export const getPrezziarioByTipologia = async ({
  db,
  tipologia,
}: {
  db: Querier;
  tipologia: TipologiaPosizioneEnum;
}): Promise<PrezziarioByTipologia> => {
  try {
    const { acconto, saldi } = await db.transaction().execute(async (trx) => {
      let qry = trx
        .selectFrom("prezziario")
        .select(["idprezziario", "prezzo_cent", "nome_it", "nome_en", "sconto"])
        .where("isAcconto", "=", true)
        .where("isSaldo", "=", false)
        .where("isActive", "=", true);

      if (tipologia == TipologiaPosizioneEnum.Transitorio) {
        qry = qry.where("isTransitorio", "=", true);
      } else if (tipologia == TipologiaPosizioneEnum.Stabile) {
        qry = qry.where("isStabile", "=", true);
      }

      const acconto = await qry.executeTakeFirst();

      if (!acconto) {
        throw new TRPCError({
          code: "NOT_FOUND",
          message: "Acconto not found",
        });
      }
      let qry2 = trx
        .selectFrom("prezziario")
        .select(["idprezziario", "prezzo_cent", "nome_it", "nome_en", "sconto"])
        .where("isAcconto", "=", false)
        .where("isSaldo", "=", true)
        .where("isActive", "=", true);
      if (tipologia == TipologiaPosizioneEnum.Transitorio) {
        qry2 = qry2.where("isTransitorio", "=", true);
      } else if (tipologia == TipologiaPosizioneEnum.Stabile) {
        qry2 = qry2.where("isStabile", "=", true);
      }
      const saldi = await qry2.orderBy("prezzo_cent", "asc").execute();

      if (!saldi) {
        throw new TRPCError({
          code: "NOT_FOUND",
          message: "Saldi not found",
        });
      }

      return { acconto, saldi };
    });

    return { acconto, saldi };
  } catch (error) {
    throw new TRPCError({
      code: "INTERNAL_SERVER_ERROR",
      message:
        "Error getting prezziario by tipologia: " + (error as Error).message,
    });
  }
};

export const getPrezziarioConsulenza = async ({ db }: { db: Querier }) => {
  try {
    return await db.transaction().execute(async (trx) => {
      const prezzi = await trx
        .selectFrom("prezziario")
        .select(["idprezziario", "prezzo_cent", "nome_it", "nome_en", "sconto"])
        .where("isConsulenza", "=", true)
        .where("isAcconto", "=", false)
        .where("isSaldo", "=", false)
        .where("isActive", "=", true)
        .where("isStabile", "=", true)
        .orderBy("prezzo_cent", "asc")
        .execute();

      if (!prezzi || prezzi.length !== 3) {
        throw new TRPCError({
          code: "NOT_FOUND",
          message: "Consulenza prezzi not found",
        });
      }

      return prezzi;
    });
  } catch (error) {
    throw new TRPCError({
      code: "INTERNAL_SERVER_ERROR",
      message:
        "Error getting prezziario by tipologia: " + (error as Error).message,
    });
  }
};
