import { NextRequest, NextResponse } from "next/server";
import { getCurrentUser } from "@/lib/auth";
import { queryRaw } from "@/lib/db";
import { MY_SPEND_SCOPE, STATEMENTS_JOIN, EXCLUDE_NON_SPEND, EXCLUDE_RECONCILED_SOURCE, EFFECTIVE_CATEGORY, mySplitOf, toDateStr } from "@/lib/analytics-sql";

// Split-adjusted amount helper (positive for spend, negative for refunds)
const MY_AMOUNT = mySplitOf(`COALESCE(t.amount_aud, t.amount)`);
const SPEND_EXPR = `
  CASE
    WHEN t.transaction_type IN ('refund', 'credit') THEN -(${MY_AMOUNT})
    ELSE (${MY_AMOUNT})
  END
`;

export async function GET(req: NextRequest) {
  const user = await getCurrentUser(req);
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

  const { searchParams } = new URL(req.url);
  const months = Math.min(24, Math.max(1, Number(searchParams.get("months") || "12")));

  const cutoff = new Date();
  cutoff.setMonth(cutoff.getMonth() - months);
  const fromDate = toDateStr(cutoff);

  // Merchant aggregates — net spend (debits + fees - refunds/credits)
  const rows = await queryRaw<{
    merchant: string;
    category: string;
    debit_count: number;
    refund_count: number;
    gross_spend: number;
    total_refunds: number;
    net_spend: number;
    avg_debit: number;
    first_seen: string;
    last_seen: string;
    months_active: number;
  }>(`
    SELECT
      COALESCE(o.merchant_normalized, t.merchant_normalized, t.merchant_name, t.description) as merchant,
      MODE() WITHIN GROUP (ORDER BY ${EFFECTIVE_CATEGORY}) as category,
      COUNT(*) FILTER (WHERE t.transaction_type IN ('debit', 'fee', 'interest'))::int as debit_count,
      COUNT(*) FILTER (WHERE t.transaction_type IN ('refund', 'credit'))::int as refund_count,
      COALESCE(SUM(
        CASE WHEN t.transaction_type IN ('debit', 'fee', 'interest') THEN
          ${MY_AMOUNT}
        ELSE 0 END
      ), 0)::numeric(12,2) as gross_spend,
      COALESCE(SUM(
        CASE WHEN t.transaction_type IN ('refund', 'credit') THEN
          ${MY_AMOUNT}
        ELSE 0 END
      ), 0)::numeric(12,2) as total_refunds,
      SUM(${SPEND_EXPR})::numeric(12,2) as net_spend,
      AVG(
        CASE WHEN t.transaction_type IN ('debit', 'fee', 'interest') THEN
          ${MY_AMOUNT}
        END
      )::numeric(10,2) as avg_debit,
      MIN(t.transaction_date)::text as first_seen,
      MAX(t.transaction_date)::text as last_seen,
      COUNT(DISTINCT TO_CHAR(DATE_TRUNC('month', t.transaction_date::date), 'YYYY-MM'))::int as months_active
    FROM transactions t
    ${STATEMENTS_JOIN}
    LEFT JOIN transaction_overrides o ON o.transaction_id = t.id
    LEFT JOIN transaction_splits ts ON ts.transaction_id = t.id AND ts.participant_id = $1
    WHERE ${MY_SPEND_SCOPE()}
      AND t.transaction_type IN ('debit', 'fee', 'interest', 'refund', 'credit')
      AND t.transaction_date >= $2
      AND ${EXCLUDE_NON_SPEND}
      AND ${EXCLUDE_RECONCILED_SOURCE}
    GROUP BY 1
    HAVING SUM(${SPEND_EXPR}) > 0
    ORDER BY net_spend DESC
    LIMIT 200
  `, [user.id, fromDate]);

  // Monthly net trend per merchant (top 50 by net spend)
  const topMerchants = rows.slice(0, 50).map((r) => r.merchant);

  interface TrendRow { merchant: string; month: string; total: number }
  let trendRows: TrendRow[] = [];
  if (topMerchants.length > 0) {
    trendRows = await queryRaw<TrendRow>(`
      SELECT
        COALESCE(o.merchant_normalized, t.merchant_normalized, t.merchant_name, t.description) as merchant,
        TO_CHAR(DATE_TRUNC('month', t.transaction_date::date), 'YYYY-MM') as month,
        SUM(${SPEND_EXPR})::numeric(10,2) as total
      FROM transactions t
      ${STATEMENTS_JOIN}
      LEFT JOIN transaction_overrides o ON o.transaction_id = t.id
      LEFT JOIN transaction_splits ts ON ts.transaction_id = t.id AND ts.participant_id = $1
      WHERE ${MY_SPEND_SCOPE()}
        AND t.transaction_type IN ('debit', 'fee', 'interest', 'refund', 'credit')
        AND t.transaction_date >= $2
        AND COALESCE(o.merchant_normalized, t.merchant_normalized, t.merchant_name, t.description) = ANY($3)
        AND ${EXCLUDE_NON_SPEND}
        AND ${EXCLUDE_RECONCILED_SOURCE}
      GROUP BY 1, 2
      ORDER BY 1, 2
    `, [user.id, fromDate, topMerchants]);
  }

  const trendByMerchant: Record<string, Record<string, number>> = {};
  for (const tr of trendRows) {
    if (!trendByMerchant[tr.merchant]) trendByMerchant[tr.merchant] = {};
    trendByMerchant[tr.merchant][tr.month] = Number(tr.total);
  }

  const merchants = rows.map((r) => ({
    ...r,
    debit_count: Number(r.debit_count),
    refund_count: Number(r.refund_count),
    gross_spend: Number(r.gross_spend),
    total_refunds: Number(r.total_refunds),
    net_spend: Number(r.net_spend),
    avg_debit: Number(r.avg_debit),
    months_active: Number(r.months_active),
    monthly_trend: trendByMerchant[r.merchant] || {},
  }));

  return NextResponse.json({ merchants, months });
}
