import { NextRequest, NextResponse } from "next/server";
import { S3Client, PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { db } from "@/app/db/db";
import { filesFromSurveyor } from "@/app/db/schema/files_from_surveyor";
import { and, eq } from "drizzle-orm";

// ✅ Initialize S3 Client (AWS SDK v3)
const s3 = new S3Client({
  region: process.env.RETROFIT_DATA_DEV_REGION,
  credentials: {
    accessKeyId: process.env.RETROFIT_DATA_DEV_ACCESS_KEY!,
    secretAccessKey: process.env.RETROFIT_DATA_DEV_SECRET_KEY!,
  },
});

// ✅ Helper: safely convert BigInt fields to string
function serializeBigInt<T extends Record<string, any>>(obj: T): T {
  return Object.fromEntries(
    Object.entries(obj).map(([key, value]) => [
      key,
      typeof value === "bigint" ? value.toString() : value,
    ])
  ) as T;
}

// -------------------
// 📤 POST — Upload files to S3 + Save to DB
// -------------------
export async function POST(request: NextRequest) {
  try {
    const formData = await request.formData();
    const files = formData.getAll("files") as File[];

    const portfolioIdStr = formData.get("portfolioId") as string;
    const propertyIdStr = formData.get("propertyId") as string;

    if (!portfolioIdStr || !propertyIdStr) {
      return NextResponse.json(
        { msg: "Missing portfolioId or propertyId" },
        { status: 400 }
      );
    }

    const portfolioId = BigInt(portfolioIdStr);
    const propertyId = BigInt(propertyIdStr);

    if (!files || files.length === 0) {
      return NextResponse.json({ msg: "No files uploaded" }, { status: 400 });
    }

    const uploadedFiles = await Promise.all(
      files.map(async (file) => {
        const timestamp = Date.now();
        const safeName = file.name.replace(/\s+/g, "_");
        const fileKey = `files_from_surveyor/${portfolioId}/${propertyId}/${timestamp}-${safeName}`;

        const buffer = Buffer.from(await file.arrayBuffer());

        await s3.send(
          new PutObjectCommand({
            Bucket: process.env.RETROFIT_DATA_DEV_S3_BUCKET_NAME!,
            Key: fileKey,
            Body: buffer,
            ContentType: file.type,
          })
        );

        const fileUrl = `https://${process.env.RETROFIT_DATA_DEV_S3_BUCKET_NAME}.s3.${process.env.RETROFIT_DATA_DEV_REGION}.amazonaws.com/${fileKey}`;

        return { fileKey, fileUrl };
      })
    );

    const inserted = await db
      .insert(filesFromSurveyor)
      .values(
        uploadedFiles.map((file) => ({
          portfolioId,
          propertyId,
          s3JsonUrl: file.fileUrl,
        }))
      )
      .returning();

    // ✅ Serialize BigInts before sending JSON
    const safeInserted = inserted.map(serializeBigInt);

    return NextResponse.json({ files: safeInserted }, { status: 200 });
  } catch (error) {
    console.error("❌ S3 or DB Error:", error);
    return NextResponse.json(
      { msg: "File upload failed", error: String(error) },
      { status: 500 }
    );
  }
}

// -------------------
// 📥 GET — Fetch uploaded files + Presigned URLs
// -------------------
export async function GET(request: NextRequest) {
  try {
    const { searchParams } = new URL(request.url);
    const portfolioIdStr = searchParams.get("portfolioId");
    const propertyIdStr = searchParams.get("propertyId");

    if (!portfolioIdStr || !propertyIdStr) {
      return NextResponse.json(
        { msg: "Missing portfolioId or propertyId" },
        { status: 400 }
      );
    }

    const portfolioId = BigInt(portfolioIdStr);
    const propertyId = BigInt(propertyIdStr);

    // ✅ Correct Drizzle where syntax
    const files = await db
      .select()
      .from(filesFromSurveyor)
      .where(
        and(
          eq(filesFromSurveyor.portfolioId, portfolioId),
          eq(filesFromSurveyor.propertyId, propertyId)
        )
      );

    // ✅ Add 30-min presigned URLs
    const withSignedUrls = await Promise.all(
      files.map(async (file) => {
        const key = file.s3JsonUrl.split(".amazonaws.com/")[1];
        const presignedUrl = await getSignedUrl(
          s3,
          new GetObjectCommand({
            Bucket: process.env.RETROFIT_DATA_DEV_S3_BUCKET_NAME!,
            Key: key,
          }),
          { expiresIn: 60 * 30 } // 30 minutes
        );

        return serializeBigInt({
          ...file,
          presignedUrl,
        });
      })
    );

    return NextResponse.json({ files: withSignedUrls }, { status: 200 });
  } catch (error) {
    console.error("❌ Fetch error:", error);
    return NextResponse.json(
      { msg: "Error fetching files", error: String(error) },
      { status: 500 }
    );
  }
}
