import { NextResponse } from "next/server";
import { makeUniqueFileName } from "@/lib/file-tree/naming";
import { rewriteToPublicOrigin } from "@/lib/url/rewritePublicOrigin";
import { getMnoteRuntimeConfig } from "@/lib/runtime-config";
import { isConvexEnabled } from "@/lib/convex/enabled";
import { HttpError, requireAuthContext } from "@/lib/auth/authContext";
import { api } from "@/lib/convex/api";
import { getConvexAuthedHttpClient } from "@/lib/convex/server";
import { maybeProxyForBrowserUrl } from "@/lib/url/proxyForBrowser";

export const dynamic = "force-dynamic";

type Action = "copy" | "move" | "delete" | "rename" | "restore";

interface BatchPayload {
  action: Action;
  assetIds: string[];
  targetDocumentId?: string;
  targetSubPath?: string;
  newName?: string;
}

const BUCKET = process.env.NEXT_PUBLIC_SUPABASE_MEDIA_BUCKET ?? "workspace";
const DEFAULT_DOC_BUCKET = process.env.NEXT_PUBLIC_SUPABASE_DOC_BUCKET ?? "documents";

const parseStoragePath = (fileUrl: string) => {
  try {
    const url = new URL(fileUrl);
    const segments = url.pathname.split("/").filter(Boolean);
    const objectIdx = segments.findIndex((seg) => seg === "object");
    if (objectIdx === -1 || objectIdx + 2 >= segments.length) return null;
    if (segments[objectIdx + 1] === "public") {
      const bucket = segments[objectIdx + 2];
      const path = segments.slice(objectIdx + 3).join("/");
      return { bucket, path };
    }
    if (segments[objectIdx + 1] === "sign") {
      const bucket = segments[objectIdx + 2];
      const path = segments.slice(objectIdx + 3).join("/");
      return { bucket, path };
    }
    return null;
  } catch {
    return null;
  }
};

function resolveAssetLocation(asset: any): { bucket: string; path: string } | null {
  if (asset?.storage_path) {
    return { bucket: asset.bucket || BUCKET, path: asset.storage_path };        
  }
  if (asset?.file_url) {
    return parseStoragePath(asset.file_url);
  }
  return null;
}

function sanitizeSubPath(input: string | undefined): string {
  const raw = typeof input === "string" ? input : "";
  const cleaned = raw
    .replace(/\\/g, "/")
    .split("/")
    .map((seg) => seg.trim())
    .filter((seg) => Boolean(seg) && seg !== "." && seg !== "..")
    .map((seg) => seg.replace(/[\\/]/g, "_"))
    .slice(0, 8);
  return cleaned.join("/");
}

export async function POST(request: Request) {
  if (isConvexEnabled()) {
    let auth;
    try {
      auth = await requireAuthContext();
    } catch (err) {
      if (err instanceof HttpError) {
        return NextResponse.json({ error: "未登录" }, { status: err.status });
      }
      return NextResponse.json({ error: "未登录" }, { status: 401 });
    }

    const payload = (await request.json()) as BatchPayload;
    if (!payload?.action || !payload.assetIds?.length) {
      return NextResponse.json({ error: "缺少参数" }, { status: 400 });
    }

    const client = await getConvexAuthedHttpClient();
    const assets = (await client.query(api.mediaAssets.listByIds, {
      userId: auth.userId,
      ids: payload.assetIds,
    })) as any[];

    if (!assets?.length) {
      return NextResponse.json({ error: "未找到附件" }, { status: 404 });
    }

    const nowIso = () => new Date().toISOString();

    try {
      switch (payload.action) {
        case "delete": {
          for (const a of assets) {
            await client.mutation(api.mediaAssets.patchById, {
              userId: auth.userId,
              id: String(a.id),
              patch: { deleted_at: nowIso(), deleted_by: auth.userId },
            });
          }
          return NextResponse.json({ ok: true });
        }
        case "restore": {
          for (const a of assets) {
            await client.mutation(api.mediaAssets.patchById, {
              userId: auth.userId,
              id: String(a.id),
              patch: { deleted_at: null, deleted_by: null, purged_at: null },
            });
          }
          return NextResponse.json({ ok: true });
        }
        case "rename": {
          if (payload.assetIds.length !== 1 || !payload.newName) {
            return NextResponse.json({ error: "重命名需要单个文件与新名称" }, { status: 400 });
          }
          const asset = assets[0];
          const currentName = String(asset.file_name ?? "");
          const ext = currentName.includes(".") ? `.${currentName.split(".").pop()}` : "";
          const newFileName = payload.newName.includes(".") || !ext ? payload.newName : `${payload.newName}${ext}`;
          const safeName = newFileName.replace(/[\\/]/g, "_");

          await client.mutation(api.mediaAssets.patchById, {
            userId: auth.userId,
            id: String(asset.id),
            patch: { file_name: safeName },
          });
          return NextResponse.json({ ok: true });
        }
        case "copy":
        case "move": {
          if (!payload.targetDocumentId) {
            return NextResponse.json({ error: "缺少目标页面" }, { status: 400 });
          }

          const targetDoc = await client.query(api.documents.getMeta, {
            id: payload.targetDocumentId,
          });

          if (!targetDoc) {
            return NextResponse.json({ error: "目标页面不存在" }, { status: 404 });
          }

          const existing = (await client.query(api.mediaAssets.listByDocument, {
            userId: auth.userId,
            documentId: payload.targetDocumentId,
            limit: 500,
          })) as any[];
          const existingNames = new Set<string>(
            (existing ?? []).map((r) => (r?.file_name ?? "").toString()).filter(Boolean),
          );

          const results: any[] = [];

          for (const asset of assets) {
            const fileName = makeUniqueFileName(asset.file_name ?? "附件", existingNames).replace(/[\\/]/g, "_");
            const storageId = (asset as { storage_id?: string | null })?.storage_id ?? null;
            if (!storageId) continue;

            if (payload.action === "copy") {
              const newId =
                typeof crypto.randomUUID === "function"
                  ? crypto.randomUUID()
                  : `${Date.now()}_${Math.random().toString(16).slice(2)}`;

              const created = await client.mutation(api.mediaAssets.createWithStorage, {
                userId: auth.userId,
                storageId: storageId as any,
                asset: {
                  id: newId,
                  workspace_id: String(targetDoc.workspace_id),
                  document_id: String(payload.targetDocumentId),
                  asset_type: String(asset.asset_type ?? "file"),
                  file_name: fileName,
                  file_size: typeof asset.file_size === "number" ? asset.file_size : null,
                  mime_type: (asset.mime_type ?? null) as any,
                },
              });

              results.push(created);
            } else {
              await client.mutation(api.mediaAssets.patchById, {
                userId: auth.userId,
                id: String(asset.id),
                patch: {
                  workspace_id: String(targetDoc.workspace_id),
                  document_id: String(payload.targetDocumentId),
                  file_name: fileName,
                },
              });

              results.push({ ...asset, workspace_id: String(targetDoc.workspace_id), document_id: String(payload.targetDocumentId), file_name: fileName });
            }
          }

           const safeItems = (results ?? []).map((a: any) => ({
             ...a,
             file_url: maybeProxyForBrowserUrl(request, String(a?.file_url ?? "")),
             thumbnail_url: maybeProxyForBrowserUrl(request, String(a?.thumbnail_url ?? a?.file_url ?? "")),
           }));

           return NextResponse.json({ items: safeItems });
         }
        default:
          return NextResponse.json({ error: "不支持的操作" }, { status: 400 });
      }
    } catch (err) {
      const message = err instanceof Error ? err.message : "操作失败";
      return NextResponse.json({ error: message }, { status: 500 });
    }
  }

  return NextResponse.json({ error: "当前仅支持 Convex 模式" }, { status: 501 });

  /*
  const supabase = await createSupabaseRouteClient();
  const {
    data: { session },
  } = await supabase.auth.getSession();

  if (!session) {
    return NextResponse.json({ error: "未登录" }, { status: 401 });
  }

  const payload = (await request.json()) as BatchPayload;
  if (!payload?.action || !payload.assetIds?.length) {
    return NextResponse.json({ error: "缺少参数" }, { status: 400 });
  }

  const { data: assets, error: fetchError } = await supabase
    .from("media_assets")
    .select("*")
    .in("id", payload.assetIds);

  if (fetchError) {
    return NextResponse.json({ error: fetchError.message }, { status: 500 });
  }

  if (!assets?.length) {
    return NextResponse.json({ error: "未找到附件" }, { status: 404 });
  }

  try {
    switch (payload.action) {
      case "delete": {
        // 可撤销删除：仅标记 deleted_at，真正清理（OCR/Storage/LightRAG）由后台宽限期任务处理
        const { error } = await supabase
          .from("media_assets")
          .update({
            deleted_at: new Date().toISOString(),
            deleted_by: session.user.id,
          })
          .in("id", payload.assetIds);
        if (error) throw error;
        return NextResponse.json({ ok: true });
      }
      case "restore": {
        const { error } = await supabase
          .from("media_assets")
          .update({
            deleted_at: null,
            deleted_by: null,
            purged_at: null,
          })
          .in("id", payload.assetIds);
        if (error) throw error;
        return NextResponse.json({ ok: true });
      }
      case "rename": {
        if (payload.assetIds.length !== 1 || !payload.newName) {
          return NextResponse.json({ error: "重命名需要单个文件与新名称" }, { status: 400 });
        }
        const asset = assets[0];
        const ext = asset.file_name?.includes(".") ? `.${asset.file_name.split(".").pop()}` : "";
        const newFileName = payload.newName.includes(".") || !ext ? payload.newName : `${payload.newName}${ext}`;
        const location = resolveAssetLocation(asset);
        const safeName = newFileName.replace(/[\\/]/g, "_");
        if (location) {
          const uniqueId =
            typeof crypto.randomUUID === "function"
              ? crypto.randomUUID()
              : `${Date.now()}_${Math.random().toString(16).slice(2)}`;
          const baseDir = (() => {
            const current = location.path;
            const idx = current.lastIndexOf("/");
            if (idx > 0) return current.slice(0, idx);
            return `${asset.workspace_id}/${asset.document_id}`;
          })();
          const targetPath = `${baseDir}/${Date.now()}-${uniqueId}-${safeName}`;
          const bucket = location.bucket || asset.bucket || DEFAULT_DOC_BUCKET || BUCKET;
          const moveResult = await supabase.storage.from(bucket).move(location.path, targetPath);
          if (moveResult.error) throw moveResult.error;
          const { data: signed } = await supabase.storage.from(bucket).createSignedUrl(targetPath, 60 * 60 * 24 * 7);
          let signedUrl = signed?.signedUrl ?? null;
          if (signedUrl) {
            signedUrl = rewriteToPublicOrigin(signedUrl, getMnoteRuntimeConfig().supabaseUrl);
          }
          const { error } = await supabase
            .from("media_assets")
            .update({
              file_name: safeName,
              bucket,
              storage_path: targetPath,
              file_url: signedUrl,
              thumbnail_url: signedUrl,
            })
            .eq("id", asset.id);
          if (error) throw error;
          return NextResponse.json({ ok: true });
        }
        const { error } = await supabase
          .from("media_assets")
          .update({
            file_name: safeName,
          })
          .eq("id", asset.id);
        if (error) throw error;
        return NextResponse.json({ ok: true });
      }
      case "copy":
      case "move": {
        if (!payload.targetDocumentId) {
          return NextResponse.json({ error: "缺少目标页面" }, { status: 400 });
        }
        const { data: targetDoc, error: docErr } = await supabase
          .from("documents")
          .select("workspace_id")
          .eq("id", payload.targetDocumentId)
          .single();
        if (docErr || !targetDoc) {
          return NextResponse.json({ error: "目标页面不存在" }, { status: 404 });
        }
        const { data: existingRows } = await supabase
          .from("media_assets")
          .select("file_name")
          .eq("document_id", payload.targetDocumentId);
        const existingNames = new Set<string>((existingRows ?? []).map((r) => (r.file_name ?? "").toString()).filter(Boolean));
        const results = [];
        for (const asset of assets) {
          const location = resolveAssetLocation(asset);
          if (!location) continue;
          const fileName = makeUniqueFileName(asset.file_name ?? "附件", existingNames).replace(/[\\/]/g, "_");
          const uniqueId =
            typeof crypto.randomUUID === "function"
              ? crypto.randomUUID()
              : `${Date.now()}_${Math.random().toString(16).slice(2)}`;
          const subdir = sanitizeSubPath(payload.targetSubPath);
          const prefix = `${targetDoc.workspace_id}/${payload.targetDocumentId}${subdir ? `/${subdir}` : ""}`;
          const targetPath = `${prefix}/${Date.now()}-${uniqueId}-${fileName}`;
          const bucket = location.bucket || asset.bucket || DEFAULT_DOC_BUCKET || BUCKET;
          if (payload.action === "copy") {
            const copyRes = await supabase.storage.from(bucket).copy(location.path, targetPath);
            if (copyRes.error) throw copyRes.error;
            const { data: signed } = await supabase.storage.from(bucket).createSignedUrl(targetPath, 60 * 60 * 24 * 7);
            let signedUrl = signed?.signedUrl ?? null;
            if (signedUrl) {
              signedUrl = rewriteToPublicOrigin(signedUrl, getMnoteRuntimeConfig().supabaseUrl);
            }
            const { data: inserted, error } = await supabase
              .from("media_assets")
              .insert({
                workspace_id: targetDoc.workspace_id,
                document_id: payload.targetDocumentId,
                asset_type: asset.asset_type,
                file_name: fileName,
                file_size: asset.file_size,
                mime_type: asset.mime_type,
                bucket,
                storage_path: targetPath,
                file_url: signedUrl,
                thumbnail_url: signedUrl,
                created_by: session.user.id,
              })
              .select("*")
              .single();
            if (error) throw error;
            results.push(inserted);
          } else {
            const moveRes = await supabase.storage.from(bucket).move(location.path, targetPath);
            if (moveRes.error) throw moveRes.error;
            const { data: signed } = await supabase.storage.from(bucket).createSignedUrl(targetPath, 60 * 60 * 24 * 7);
            let signedUrl = signed?.signedUrl ?? null;
            if (signedUrl) {
              signedUrl = rewriteToPublicOrigin(signedUrl, getMnoteRuntimeConfig().supabaseUrl);
            }
            const { data: updated, error } = await supabase
              .from("media_assets")
              .update({
                workspace_id: targetDoc.workspace_id,
                document_id: payload.targetDocumentId,
                storage_path: targetPath,
                file_name: fileName,
                bucket,
                file_url: signedUrl,
                thumbnail_url: signedUrl,
              })
              .eq("id", asset.id)
              .select("*")
              .single();
            if (error) throw error;
            results.push(updated);
          }
        }
        return NextResponse.json({ items: results });
      }
      default:
        return NextResponse.json({ error: "不支持的操作" }, { status: 400 });
    }
  } catch (err) {
    const message = err instanceof Error ? err.message : "操作失败";
    return NextResponse.json({ error: message }, { status: 500 });
  }
  */
}
