import type { UsersId } from "~/schemas/public/Users";
import { db, type Querier } from "~/server/db";
import { jsonArrayFrom } from "kysely/helpers/postgres";
import { TRPCError } from "@trpc/server";
import type { OrdiniOrdineId, OrdiniUpdate } from "~/schemas/public/Ordini";

export type OrdiniWPagamenti = Awaited<ReturnType<typeof getOrdini>>[number];
export const getOrdini = async (userId: UsersId | undefined) => {
  try {
    let qry = db
      .selectFrom("ordini")
      .selectAll("ordini")
      .innerJoin("users", "users.id", "ordini.userid")
      .select("users.username")
      .select((eb) => [
        jsonArrayFrom(
          eb
            .selectFrom("payments")
            .selectAll("payments")
            .whereRef("payments.ordine_id", "=", "ordini.ordine_id")
            .orderBy("payments.created_at", "desc"),
        ).as("pagamenti"),
      ]);

    if (userId) {
      qry = qry.where("ordini.userid", "=", userId);
    }
    return await qry.orderBy("created_at", "desc").execute();
  } catch (e) {
    throw new TRPCError({
      code: "INTERNAL_SERVER_ERROR",
      message: "Error fetching ordini by user ID: " + (e as Error).message,
    });
  }
};

export const getOrdineById = async (ordineId: OrdiniOrdineId) => {
  try {
    return await db
      .selectFrom("ordini")
      .selectAll("ordini")
      .innerJoin("users", "users.id", "ordini.userid")
      .select("users.username")
      .select((eb) => [
        jsonArrayFrom(
          eb
            .selectFrom("payments")
            .selectAll("payments")
            .whereRef("payments.ordine_id", "=", "ordini.ordine_id")
            .orderBy("payments.created_at", "desc"),
        ).as("pagamenti"),
      ])
      .where("ordini.ordine_id", "=", ordineId)
      .orderBy("created_at", "desc")
      .executeTakeFirstOrThrow();
  } catch (e) {
    throw new TRPCError({
      code: "INTERNAL_SERVER_ERROR",
      message: "Error fetching ordini by user ID: " + (e as Error).message,
    });
  }
};

export const removeOrder = async (ordineId: OrdiniOrdineId) => {
  try {
    await db
      .deleteFrom("ordini")
      .where("ordine_id", "=", ordineId)
      .executeTakeFirstOrThrow();
    return true;
  } catch (e) {
    throw new TRPCError({
      code: "INTERNAL_SERVER_ERROR",
      message: "Error removing order: " + (e as Error).message,
    });
  }
};

export const updateOrder = async ({
  ordineId,
  data,
}: {
  ordineId: OrdiniOrdineId;
  data: OrdiniUpdate;
}) => {
  try {
    const updated = await db
      .updateTable("ordini")
      .set(data)
      .where("ordine_id", "=", ordineId)
      .returningAll()
      .executeTakeFirstOrThrow();
    return updated;
  } catch (e) {
    throw new TRPCError({
      code: "INTERNAL_SERVER_ERROR",
      message: "Error updating order: " + (e as Error).message,
    });
  }
};

export const cleanupUnusedOrders = async ({ db }: { db: Querier }) => {
  try {
    const orders = await db
      .selectFrom("ordini")
      .select("ordini.ordine_id")
      .leftJoin("payments", "payments.ordine_id", "ordini.ordine_id")
      .where("payments.paymentstatus", "is", null)
      .where("ordini.isActive", "=", false)
      .distinct()
      .execute();

    if (orders.length === 0) {
      return "ok";
    }
    const ordineIds = orders.map((o) => o.ordine_id);
    await db.deleteFrom("ordini").where("ordine_id", "in", ordineIds).execute();

    return "ok";
  } catch (e) {
    throw new TRPCError({
      code: "INTERNAL_SERVER_ERROR",
      message: "Error cleaning up old orders: " + (e as Error).message,
    });
  }
};
