import { and, eq, sql } from "drizzle-orm";
import type { db as prodDb } from "../../db/index.ts";
import { communityPrices, items } from "../../db/schema.ts";

type Db = typeof prodDb;

/**
 * Check if a user owns an item linked to a given global item.
 * Per D-05: community price submissions require collection ownership.
 */
export async function validateOwnership(
	db: Db,
	userId: number,
	globalItemId: number,
): Promise<boolean> {
	const [row] = await db
		.select({ count: sql<number>`COUNT(*)` })
		.from(items)
		.where(
			and(eq(items.userId, userId), eq(items.globalItemId, globalItemId)),
		);
	return (row?.count ?? 0) > 0;
}

/**
 * Submit or update a community price for a global item.
 * Returns null if ownership validation fails.
 */
export async function submitCommunityPrice(
	db: Db,
	data: {
		globalItemId: number;
		userId: number;
		market: string;
		currency: string;
		priceCents: number;
		priceDate?: string | null;
		sourceType: "purchased" | "researched";
	},
) {
	// Per D-05: ownership validation
	const ownsItem = await validateOwnership(db, data.userId, data.globalItemId);
	if (!ownsItem) return null;

	const [row] = await db
		.insert(communityPrices)
		.values({
			globalItemId: data.globalItemId,
			userId: data.userId,
			market: data.market,
			currency: data.currency,
			priceCents: data.priceCents,
			priceDate: data.priceDate ? new Date(data.priceDate) : null,
			sourceType: data.sourceType,
		})
		.onConflictDoUpdate({
			target: [
				communityPrices.globalItemId,
				communityPrices.userId,
				communityPrices.sourceType,
			],
			set: {
				priceCents: data.priceCents,
				priceDate: data.priceDate ? new Date(data.priceDate) : null,
				market: data.market,
				currency: data.currency,
			},
		})
		.returning();

	return row;
}

/**
 * Get community price statistics for a global item.
 * Per D-21: returns per-market median and report count.
 * Only returns stats where report count >= 3.
 */
export async function getCommunityPriceStats(
	db: Db,
	globalItemId: number,
	market?: string,
) {
	const conditions = [eq(communityPrices.globalItemId, globalItemId)];
	if (market) {
		conditions.push(eq(communityPrices.market, market));
	}

	const rows = await db
		.select({
			market: communityPrices.market,
			currency: communityPrices.currency,
			medianPrice:
				sql<number>`PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY ${communityPrices.priceCents})`.as(
					"median_price",
				),
			reportCount: sql<number>`CAST(COUNT(*) AS INT)`.as("report_count"),
		})
		.from(communityPrices)
		.where(and(...conditions))
		.groupBy(communityPrices.market, communityPrices.currency)
		.having(sql`COUNT(*) >= 3`);

	return rows.map((r) => ({
		market: r.market,
		currency: r.currency,
		medianPrice: Math.round(r.medianPrice),
		reportCount: r.reportCount,
	}));
}
