import { and, asc, eq, inArray } from 'drizzle-orm';
import type { DrizzleClient } from '@/server/db/client';
import { dealSkus, dealVariantAxes, dealVariantOptions } from '@/server/db/schema';
import { getQtyTiersForSkus } from '@/server/db/queries/sku-qty-tiers.js';

export interface SkuRow {
  id: string;
  dealId: string;
  optionIds: string[];
  optionIdsHash: string;
  originalPrice: string;
  discountPercent: number;
  discountedPrice: string;
  quantityTotal: number;
  quantitySold: number;
  isActive: boolean;
  qtyTiers: { minQty: number; discountPercent: number }[];
}

export interface AxisWithOptions {
  id: string;
  axisOrder: number;
  kind: 'SIZE' | 'COLOR' | 'TIMESLOT' | 'CUSTOM';
  nameHe: string;
  nameEn: string;
  isActive: boolean;
  options: {
    id: string;
    optionOrder: number;
    valueCode: string;
    labelHe: string;
    labelEn: string;
    slotStart: Date | null;
    slotEnd: Date | null;
    swatchHex: string | null;
    isActive: boolean;
  }[];
}

export interface DealWithSkus {
  dealId: string;
  axes: AxisWithOptions[];
  skus: SkuRow[];
}

export async function getDealWithSkus(db: DrizzleClient, dealId: string): Promise<DealWithSkus> {
  const axes = await db
    .select()
    .from(dealVariantAxes)
    .where(eq(dealVariantAxes.dealId, dealId))
    .orderBy(asc(dealVariantAxes.axisOrder));

  const axisIds = axes.map((a) => a.id);
  const allOptions = axisIds.length
    ? await db
        .select()
        .from(dealVariantOptions)
        .where(inArray(dealVariantOptions.axisId, axisIds))
    : [];

  const skuRows = await db
    .select()
    .from(dealSkus)
    .where(eq(dealSkus.dealId, dealId));

  const tierMap = await getQtyTiersForSkus(db, skuRows.map((s) => s.id));

  return {
    dealId,
    axes: axes.map((a) => ({
      id: a.id,
      axisOrder: a.axisOrder,
      kind: a.kind,
      nameHe: a.nameHe,
      nameEn: a.nameEn,
      isActive: a.isActive,
      options: allOptions
        .filter((o) => o.axisId === a.id)
        .sort((x, y) => x.optionOrder - y.optionOrder)
        .map((o) => ({
          id: o.id,
          optionOrder: o.optionOrder,
          valueCode: o.valueCode,
          labelHe: o.labelHe,
          labelEn: o.labelEn,
          slotStart: o.slotStart,
          slotEnd: o.slotEnd,
          swatchHex: o.swatchHex,
          isActive: o.isActive,
        })),
    })),
    skus: skuRows.map((row) => ({
      id: row.id,
      dealId: row.dealId,
      optionIds: row.optionIds,
      optionIdsHash: row.optionIdsHash,
      originalPrice: row.originalPrice,
      discountPercent: row.discountPercent,
      discountedPrice: row.discountedPrice,
      quantityTotal: row.quantityTotal,
      quantitySold: row.quantitySold,
      isActive: row.isActive,
      qtyTiers: tierMap.get(row.id) ?? [],
    })),
  };
}

export async function getDefaultSku(db: DrizzleClient, dealId: string): Promise<SkuRow> {
  const rows = await db
    .select()
    .from(dealSkus)
    .where(and(eq(dealSkus.dealId, dealId), eq(dealSkus.optionIdsHash, 'default')));
  if (rows.length === 0) {
    throw new Error(`No default SKU for deal ${dealId}`);
  }
  const row = rows[0]!;
  const tiers = await getQtyTiersForSkus(db, [row.id]);
  return {
    id: row.id,
    dealId: row.dealId,
    optionIds: row.optionIds,
    optionIdsHash: row.optionIdsHash,
    originalPrice: row.originalPrice,
    discountPercent: row.discountPercent,
    discountedPrice: row.discountedPrice,
    quantityTotal: row.quantityTotal,
    quantitySold: row.quantitySold,
    isActive: row.isActive,
    qtyTiers: tiers.get(row.id) ?? [],
  };
}
