import { db } from "@/db";
import {
  offer_macros,
  offer_micros,
  offer_services,
  offer_micro_services,
} from "@/db/schema";
import type { OfferMacro, OfferMicro, OfferService } from "@/db/schema";
import { eq, asc, inArray, sql } from "drizzle-orm";

export type MicroWithServices = OfferMicro & {
  services: Array<{ id: string; name: string; price: string }>;
  cumulative_price: string;
};

export type MacroWithMicros = OfferMacro & {
  micros: MicroWithServices[];
};

export async function getCatalogWithMicros(): Promise<MacroWithMicros[]> {
  const macros = await db
    .select()
    .from(offer_macros)
    .orderBy(asc(offer_macros.sort_order), asc(offer_macros.created_at));

  if (macros.length === 0) return [];

  const macroIds = macros.map((m) => m.id);

  const micros = await db
    .select()
    .from(offer_micros)
    .where(inArray(offer_micros.macro_id, macroIds))
    .orderBy(asc(offer_micros.sort_order));

  const microIds = micros.map((m) => m.id);

  if (microIds.length === 0) {
    return macros.map((m) => ({ ...m, micros: [] }));
  }

  // Fetch junction rows + service data in one query
  const assignments = await db
    .select({
      micro_id: offer_micro_services.micro_id,
      service_id: offer_services.id,
      name: offer_services.name,
      price: offer_services.price,
    })
    .from(offer_micro_services)
    .innerJoin(offer_services, eq(offer_micro_services.service_id, offer_services.id))
    .where(inArray(offer_micro_services.micro_id, microIds));

  // Cumulative price per micro
  const cumulRows = await db
    .select({
      micro_id: offer_micro_services.micro_id,
      cumulative_price: sql<string>`coalesce(sum(${offer_services.price}::numeric), 0)`,
    })
    .from(offer_micro_services)
    .innerJoin(offer_services, eq(offer_micro_services.service_id, offer_services.id))
    .where(inArray(offer_micro_services.micro_id, microIds))
    .groupBy(offer_micro_services.micro_id);

  const cumulMap = new Map(cumulRows.map((r) => [r.micro_id, r.cumulative_price]));

  const microsWithServices: MicroWithServices[] = micros.map((micro) => ({
    ...micro,
    services: assignments
      .filter((a) => a.micro_id === micro.id)
      .map((a) => ({ id: a.service_id, name: a.name, price: String(a.price) })),
    cumulative_price: cumulMap.get(micro.id) ?? "0",
  }));

  return macros.map((macro) => ({
    ...macro,
    micros: microsWithServices.filter((m) => m.macro_id === macro.id),
  }));
}

export async function getAllOfferServices(): Promise<OfferService[]> {
  return db
    .select()
    .from(offer_services)
    .where(eq(offer_services.active, true))
    .orderBy(asc(offer_services.name));
}

// Returns assigned service IDs for a given micro-offer (used by ServiceCheckboxList)
export async function getMicroAssignedServiceIds(microId: string): Promise<string[]> {
  const rows = await db
    .select({ service_id: offer_micro_services.service_id })
    .from(offer_micro_services)
    .where(eq(offer_micro_services.micro_id, microId));
  return rows.map((r) => r.service_id);
}
