import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { and, eq, inArray } from "drizzle-orm";
import { getServerSession } from "next-auth";
import { AuthOptions } from "@/app/api/auth/[...nextauth]/authOptions";
import { db } from "@/app/db/db";
import {
  userPortfolioConfig,
  userPortfolioFolders,
} from "@/app/db/schema/user_portfolio_config";
import { planFolderDeletion } from "@/app/lib/portfolioUserConfig";

const RenameSchema = z.object({
  name: z.string().trim().min(1).max(120),
});

const FolderIdSchema = z.string().regex(/^\d+$/);

export async function PATCH(
  req: NextRequest,
  props: { params: Promise<{ folderId: string }> },
) {
  try {
    const session = await getServerSession(AuthOptions);
    if (!session?.user?.dbId) {
      return NextResponse.json({ error: "Unauthenticated" }, { status: 401 });
    }
    const userId = session.user.dbId;

    const { folderId } = await props.params;
    if (!FolderIdSchema.safeParse(folderId).success) {
      return NextResponse.json({ error: "Folder not found" }, { status: 404 });
    }

    const parsed = RenameSchema.safeParse(await req.json());
    if (!parsed.success) {
      return NextResponse.json({ error: "Invalid folder name" }, { status: 400 });
    }

    const renamed = await db
      .update(userPortfolioFolders)
      .set({ name: parsed.data.name, updatedAt: new Date() })
      .where(
        and(
          eq(userPortfolioFolders.id, BigInt(folderId)),
          eq(userPortfolioFolders.userId, userId),
        ),
      )
      .returning({ id: userPortfolioFolders.id });

    if (renamed.length === 0) {
      return NextResponse.json({ error: "Folder not found" }, { status: 404 });
    }
    return NextResponse.json({ ok: true });
  } catch (err) {
    console.error("Error renaming folder:", err);
    return NextResponse.json({ error: "Server error" }, { status: 500 });
  }
}

// Folder deletion never deletes portfolios — it unfiles them. The same-owner
// FK is NO ACTION, so unfile + delete must happen in one transaction,
// unfile first (see planFolderDeletion).
export async function DELETE(
  _req: NextRequest,
  props: { params: Promise<{ folderId: string }> },
) {
  try {
    const session = await getServerSession(AuthOptions);
    if (!session?.user?.dbId) {
      return NextResponse.json({ error: "Unauthenticated" }, { status: 401 });
    }
    const userId = session.user.dbId;

    const { folderId } = await props.params;
    if (!FolderIdSchema.safeParse(folderId).success) {
      return NextResponse.json({ error: "Folder not found" }, { status: 404 });
    }

    const configs = await db
      .select({
        id: userPortfolioConfig.id,
        folderId: userPortfolioConfig.folderId,
      })
      .from(userPortfolioConfig)
      .where(eq(userPortfolioConfig.userId, userId));

    const plan = planFolderDeletion({ folderId: BigInt(folderId), configs });

    const deleted = await db.transaction(async (tx) => {
      if (plan.unfileConfigIds.length > 0) {
        await tx
          .update(userPortfolioConfig)
          .set({ folderId: null, updatedAt: new Date() })
          .where(inArray(userPortfolioConfig.id, plan.unfileConfigIds));
      }
      return tx
        .delete(userPortfolioFolders)
        .where(
          and(
            eq(userPortfolioFolders.id, plan.deleteFolderId),
            eq(userPortfolioFolders.userId, userId),
          ),
        )
        .returning({ id: userPortfolioFolders.id });
    });

    if (deleted.length === 0) {
      return NextResponse.json({ error: "Folder not found" }, { status: 404 });
    }
    return NextResponse.json({ ok: true });
  } catch (err) {
    console.error("Error deleting folder:", err);
    return NextResponse.json({ error: "Server error" }, { status: 500 });
  }
}
