import { S3Client, DeleteObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { NextRequest, NextResponse } from "next/server";
import { cookies } from "next/headers";
import { sql } from "@/db";

const ALLOWED = ["image/jpeg", "image/jpg", "image/png", "image/webp", "image/heic"];

async function getAuthedUserId(): Promise<string | null> {
  const cookieStore = await cookies();
  const token = cookieStore.get("tia_session")?.value;
  if (!token) return null;
  const rows = await sql`
    SELECT user_id FROM sessions
    WHERE session_token = ${token} AND expires > NOW()
    LIMIT 1
  `;
  return rows[0]?.user_id ?? null;
}

function makeR2Client() {
  const accountId = process.env.R2_ACCOUNT_ID!;
  const accessKeyId = process.env.R2_ACCESS_KEY_ID!;
  const secretAccessKey = process.env.R2_SECRET_ACCESS_KEY!;
  return new S3Client({
    region: "auto",
    endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
    credentials: { accessKeyId, secretAccessKey },
  });
}

async function deleteOldAvatar(oldUrl: string | null) {
  if (!oldUrl) return;
  const baseUrl = process.env.R2_PUBLIC_URL || `https://pub-${process.env.R2_ACCOUNT_ID}.r2.dev`;
  if (!oldUrl.startsWith(baseUrl + "/")) return;
  const key = oldUrl.slice(baseUrl.length + 1);
  if (!key.startsWith("avatars/")) return; // only delete our own uploads
  try {
    const client = makeR2Client();
    await client.send(new DeleteObjectCommand({
      Bucket: process.env.R2_BUCKET_NAME!,
      Key: key,
    }));
  } catch (e) {
    console.error("Failed to delete old avatar from R2:", e);
    // non-fatal
  }
}

// POST — step 1: generate R2 key + presigned URL, return key + publicUrl to client
export async function POST(req: NextRequest) {
  const userId = await getAuthedUserId();
  if (!userId) return NextResponse.json({ error: "Not authenticated" }, { status: 401 });

  const { contentType, filename } = await req.json();
  if (!contentType || !ALLOWED.includes(contentType)) {
    return NextResponse.json({ error: "Unsupported file type. Use JPEG, PNG, or WebP." }, { status: 400 });
  }

  const accountId = process.env.R2_ACCOUNT_ID;
  const bucket    = process.env.R2_BUCKET_NAME;
  const publicUrl = process.env.R2_PUBLIC_URL || `https://pub-${accountId}.r2.dev`;

  if (!accountId || !process.env.R2_ACCESS_KEY_ID || !process.env.R2_SECRET_ACCESS_KEY || !bucket) {
    return NextResponse.json({ error: "Storage not configured" }, { status: 500 });
  }

  const ext = (filename?.split(".").pop() || "jpg").toLowerCase();
  const key = `avatars/${userId}/${Date.now()}.${ext}`;

  const client = makeR2Client();
  const uploadUrl = await getSignedUrl(
    client,
    new PutObjectCommand({ Bucket: bucket, Key: key, ContentType: contentType }),
    { expiresIn: 3600 }
  );

  return NextResponse.json({ key, uploadUrl, publicUrl: `${publicUrl}/${key}` });
}

// PATCH — step 3: save new avatarUrl to DB, delete old R2 object
export async function PATCH(req: NextRequest) {
  const userId = await getAuthedUserId();
  if (!userId) return NextResponse.json({ error: "Not authenticated" }, { status: 401 });

  const { avatarUrl } = await req.json();
  if (!avatarUrl) return NextResponse.json({ error: "avatarUrl required" }, { status: 400 });

  // Fetch old URL before overwriting
  const existing = await sql`SELECT image FROM users WHERE id = ${userId} LIMIT 1`;
  const oldUrl: string | null = existing[0]?.image ?? null;

  await sql`UPDATE users SET image = ${avatarUrl}, updated_at = NOW() WHERE id = ${userId}`;

  // Clean up old R2 object
  if (oldUrl && oldUrl !== avatarUrl) await deleteOldAvatar(oldUrl);

  return NextResponse.json({ success: true, avatarUrl });
}

// DELETE — remove avatar: clear DB + delete R2 object
export async function DELETE(_req: NextRequest) {
  const userId = await getAuthedUserId();
  if (!userId) return NextResponse.json({ error: "Not authenticated" }, { status: 401 });

  const existing = await sql`SELECT image FROM users WHERE id = ${userId} LIMIT 1`;
  const oldUrl: string | null = existing[0]?.image ?? null;

  await sql`UPDATE users SET image = NULL, updated_at = NOW() WHERE id = ${userId}`;

  await deleteOldAvatar(oldUrl);

  return NextResponse.json({ success: true });
}
