import { NextRequest, NextResponse } from "next/server";
import { prisma } from "@/lib/db";
import { queryRaw } from "@/lib/db";
import { getCurrentUser } from "@/lib/auth";
import { canAccessTransactions } from "@/lib/queries";

interface SplitInput {
  participant_id: number;
  share_percent: number;
}

interface SplitRow {
  id: number;
  transaction_id: number;
  participant_id: number;
  name: string;
  share_percent: number;
  settled: boolean;
  settled_at: string | null;
  created_at: string;
}

export async function GET(
  req: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  const user = await getCurrentUser(req);
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 403 });
  const { id } = await params;
  if (!(await canAccessTransactions(user.id, [Number(id)]))) {
    return NextResponse.json({ error: "Not found" }, { status: 404 });
  }
  const splits = await queryRaw<SplitRow>(
    `SELECT ts.*, p.name
     FROM transaction_splits ts
     JOIN participants p ON p.id = ts.participant_id
     WHERE ts.transaction_id = $1
     ORDER BY p.name`,
    [Number(id)]
  );
  return NextResponse.json(splits);
}

/**
 * Remove every split — un-share the transaction.
 *
 * POST cannot express this: it requires shares totalling 100%, and an empty
 * array is not that. Without this the order panel's "Shared 50/50" toggle had
 * no way back, and pressing it to un-share failed with "splits array required".
 */
export async function DELETE(
  req: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  const user = await getCurrentUser(req);
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 403 });
  const { id } = await params;
  const transactionId = Number(id);
  if (!(await canAccessTransactions(user.id, [transactionId]))) {
    return NextResponse.json({ error: "Not found" }, { status: 404 });
  }
  const removed = await prisma.transaction_splits.deleteMany({
    where: { transaction_id: transactionId },
  });
  return NextResponse.json({ removed: removed.count });
}

export async function POST(
  req: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  const user = await getCurrentUser(req);
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 403 });
  const { id } = await params;
  const transactionId = Number(id);
  if (!(await canAccessTransactions(user.id, [transactionId]))) {
    return NextResponse.json({ error: "Not found" }, { status: 404 });
  }
  const { splits } = (await req.json()) as { splits: SplitInput[] };

  if (!splits || !Array.isArray(splits) || splits.length === 0) {
    return NextResponse.json({ error: "splits array required" }, { status: 400 });
  }

  const total = splits.reduce((sum, s) => sum + Number(s.share_percent), 0);
  if (Math.abs(total - 100) > 0.01) {
    return NextResponse.json(
      { error: `Shares must sum to 100%, got ${total}%` },
      { status: 400 }
    );
  }

  // Carry `settled` across the rewrite.
  //
  // This replaces every split rather than editing in place, so without this the
  // recreated rows take the column default of false — silently converting a
  // discharged historical obligation into a live debt. That is not theoretical:
  // 657 pre-2026 transactions carry settled splits imported from
  // SplitMyExpenses, $37,233.28 of balance that the carryover (transaction
  // 2348) already accounts for. Editing one would double-count its share, and
  // nothing on screen would say so.
  //
  // Changing someone's percentage does not re-open the obligation — it was
  // settled outside this app and stays settled. A participant added who was not
  // there before is a genuinely new obligation and correctly starts unsettled.
  const previous = await queryRaw<{
    participant_id: number;
    settled: boolean;
    settled_at: string | null;
  }>(
    `SELECT participant_id, settled, settled_at
       FROM transaction_splits WHERE transaction_id = $1`,
    [transactionId]
  );
  const settledBefore = new Map(
    previous.map((p) => [p.participant_id, { settled: p.settled, settled_at: p.settled_at }])
  );

  // Replace all splits for this transaction atomically
  await prisma.$transaction([
    prisma.transaction_splits.deleteMany({ where: { transaction_id: transactionId } }),
    ...splits.map((s) => {
      const before = settledBefore.get(s.participant_id);
      return prisma.transaction_splits.create({
        data: {
          transaction_id: transactionId,
          participant_id: s.participant_id,
          share_percent: s.share_percent,
          settled: before?.settled ?? false,
          settled_at: before?.settled_at ? new Date(before.settled_at) : null,
        },
      });
    }),
  ]);

  const result = await queryRaw<SplitRow>(
    `SELECT ts.*, p.name FROM transaction_splits ts
     JOIN participants p ON p.id = ts.participant_id
     WHERE ts.transaction_id = $1 ORDER BY p.name`,
    [transactionId]
  );

  return NextResponse.json(result);
}
