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

/**
 * Fees and interest over an explicit window.
 *
 * This used to aggregate every statement ever imported with no date filter, and
 * the UI printed the result with no period label — so a lifetime-to-date total
 * read as a current-period one, and grew forever. `months=0` asks for all time
 * deliberately, which is a different claim from asking for it by accident.
 */
export async function GET(req: NextRequest) {
  const user = await getCurrentUser(req);
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 403 });

  const { searchParams } = new URL(req.url);
  const monthsParam = Number(searchParams.get("months") ?? "12");
  const months = Number.isFinite(monthsParam) ? Math.min(Math.max(monthsParam, 0), 120) : 12;
  const allTime = months === 0;

  const now = new Date();
  const from = new Date(now.getFullYear(), now.getMonth() - months + 1, 1);
  const fromStr = toDateStr(from);
  const toStr = toDateStr(new Date(now.getFullYear(), now.getMonth() + 1, 1));

  // A statement is dated by the period it covers, not by when it was imported.
  const stmtWindow = allTime ? "" : `AND billing_end_date >= $2 AND billing_end_date < $3`;
  const txnWindow = allTime ? "" : `AND t.transaction_date >= $2 AND t.transaction_date < $3`;
  const windowParams = allTime ? [] : [fromStr, toStr];

  // Statement-level fees and interest (aggregated by Gemini from the PDF)
  const stmtRows = await queryRaw<{
    bank_name: string;
    fees: string;
    interest: string;
  }>(
    `SELECT
      bank_name,
      SUM(COALESCE(fees_charged, 0))::numeric(12,2) AS fees,
      SUM(COALESCE(interest_charged, 0))::numeric(12,2) AS interest
    FROM statements
    WHERE owner_id = $1
    ${stmtWindow}
    GROUP BY bank_name
    HAVING SUM(COALESCE(fees_charged, 0)) + SUM(COALESCE(interest_charged, 0)) > 0
    ORDER BY (SUM(COALESCE(fees_charged, 0)) + SUM(COALESCE(interest_charged, 0))) DESC`,
    [user.id, ...windowParams]
  );

  // Transaction-level fee and interest line items (split-adjusted)
  const txnRows = await queryRaw<{
    id: number;
    transaction_date: string;
    description: string;
    merchant_name: string | null;
    transaction_type: string;
    my_amount: string;
    bank_name: string;
  }>(
    `SELECT
      t.id,
      t.transaction_date,
      t.description,
      t.merchant_name,
      t.transaction_type,
      ${mySplitOf(`COALESCE(t.amount_aud, t.amount)`)}::numeric(12,2) AS my_amount,
      COALESCE(s.bank_name, 'Manual') AS bank_name
    FROM transactions t
    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
    ${STATEMENTS_JOIN}
    WHERE ${MY_SPEND_SCOPE()}
      AND t.transaction_type IN ('fee', 'interest')
      AND ${EXCLUDE_RECONCILED_SOURCE}
      ${txnWindow}
    ORDER BY t.transaction_date DESC`,
    [user.id, ...windowParams]
  );

  const by_bank = stmtRows.map((r) => ({
    bank_name: r.bank_name,
    fees: Number(r.fees),
    interest: Number(r.interest),
    total: Number(r.fees) + Number(r.interest),
  }));

  const transactions = txnRows.map((r) => ({
    ...r,
    my_amount: Number(r.my_amount),
  }));

  // Totals from statement-level data (more complete — Gemini reads the statement summary)
  const total_fees = by_bank.reduce((s, r) => s + r.fees, 0);
  const total_interest = by_bank.reduce((s, r) => s + r.interest, 0);

  return NextResponse.json({
    by_bank,
    transactions,
    total_fees,
    total_interest,
    // The period is part of the answer — the client must be able to say what
    // window these totals cover rather than implying "now".
    period: { months, from: allTime ? null : fromStr, to: allTime ? null : toStr, all_time: allTime },
  });
}
