import { eq, and, isNull, isNotNull } from "drizzle-orm";
import { db } from "@/db";
import { quotes, quote_items, offer_phases, offer_micros } from "@/db/schema";

// Public view: safe for client API (NO line item prices exposed)
export type PublicQuoteView = {
  id: string;
  token: string;
  state: "draft" | "sent" | "viewed" | "accepted" | "rejected";
  accepted_total: string;
  accepted_at: Date | null;
  offerName: string;
  phaseSummary: Array<{
    id: string;
    title: string;
    serviceCount: number;
  }>;
};

// Get quote for public page (token-gated, no line items)
export async function getQuoteByToken(token: string): Promise<PublicQuoteView | null> {
  const [quote] = await db
    .select({
      id: quotes.id,
      token: quotes.token,
      state: quotes.state,
      accepted_total: quotes.accepted_total,
      accepted_at: quotes.accepted_at,
      offer_micro_id: quotes.offer_micro_id,
    })
    .from(quotes)
    .where(eq(quotes.token, token))
    .limit(1);

  if (!quote) return null;

  // Fetch offer name
  const [offerData] = await db
    .select({ public_name: offer_micros.public_name })
    .from(offer_micros)
    .where(eq(offer_micros.id, quote.offer_micro_id))
    .limit(1);

  const offerName = offerData?.public_name || "";

  // Fetch phase summary (count items per phase)
  const phases = await db
    .select({
      id: offer_phases.id,
      title: offer_phases.title,
      itemId: quote_items.id,
    })
    .from(offer_phases)
    .leftJoin(quote_items, eq(quote_items.offer_phase_id, offer_phases.id))
    .where(eq(offer_phases.micro_id, quote.offer_micro_id));

  // Group by phase and count items
  const phaseSummaryMap = new Map<
    string,
    { id: string; title: string; serviceCount: number }
  >();

  for (const phase of phases) {
    if (!phaseSummaryMap.has(phase.id)) {
      phaseSummaryMap.set(phase.id, {
        id: phase.id,
        title: phase.title,
        serviceCount: 0,
      });
    }
    if (phase.itemId) {
      const current = phaseSummaryMap.get(phase.id)!;
      current.serviceCount += 1;
    }
  }

  const phaseSummary = Array.from(phaseSummaryMap.values());

  return {
    id: quote.id,
    token: quote.token,
    state: quote.state as "draft" | "sent" | "viewed" | "accepted" | "rejected",
    accepted_total: quote.accepted_total.toString(),
    accepted_at: quote.accepted_at,
    offerName,
    phaseSummary,
  };
}

// Get quote for admin (includes line items and full data)
export async function getQuoteByTokenAdmin(token: string) {
  const [quote] = await db
    .select()
    .from(quotes)
    .where(eq(quotes.token, token))
    .limit(1);

  if (!quote) return null;

  const items = await db
    .select()
    .from(quote_items)
    .where(eq(quote_items.quote_id, quote.id));

  return {
    ...quote,
    items,
  };
}

// Check if quote is already accepted (immutability guard)
export async function isQuoteAccepted(token: string): Promise<boolean> {
  const [quote] = await db
    .select({ accepted_at: quotes.accepted_at })
    .from(quotes)
    .where(and(eq(quotes.token, token), isNotNull(quotes.accepted_at)))
    .limit(1);

  return !!quote;
}

// Get all quotes for a client (admin view)
export async function getQuotesByClientId(clientId: string) {
  return db
    .select()
    .from(quotes)
    .where(eq(quotes.client_id, clientId));
}

// Get all quotes for an offer (admin view)
export async function getQuotesByOfferId(offerId: string) {
  return db
    .select()
    .from(quotes)
    .where(eq(quotes.offer_micro_id, offerId));
}
