import { NextRequest, NextResponse } from "next/server";
import { GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

import { getBucketStorageUsage } from "@/lib/dto/files";
import { getMultipleConfigs } from "@/lib/dto/system-config";
import { checkUserStatus } from "@/lib/dto/user";
import { createS3Client } from "@/lib/s3";
import { getCurrentUser } from "@/lib/session";
import { generateFileKey } from "@/lib/utils";

export async function POST(request: NextRequest) {
  try {
    const user = checkUserStatus(await getCurrentUser());
    if (user instanceof Response) return user;

    const { provider, bucket, files, prefix } = await request.json();

    if (!bucket || !files || !Array.isArray(files)) {
      return NextResponse.json("Invalid request parameters", { status: 400 });
    }

    const configs = await getMultipleConfigs(["s3_config_list"]);
    if (!configs || !configs.s3_config_list) {
      return NextResponse.json("Invalid S3 configs", {
        status: 400,
      });
    }

    const providerChannel = configs.s3_config_list.find(
      (c) => c.provider_name === provider,
    );
    if (!providerChannel) {
      return NextResponse.json("Provider does not exist", {
        status: 400,
      });
    }

    const buckets = providerChannel.buckets || [];
    if (!buckets.find((b) => b.bucket === bucket)) {
      return NextResponse.json("Bucket does not exist", {
        status: 400,
      });
    }

    const bucketConfig = buckets.find((b) => b.bucket === bucket);
    if (bucketConfig?.file_size) {
      for (const file of files) {
        if (Number(file.size) > Number(bucketConfig?.file_size)) {
          return Response.json(`File size limit exceeded`, {
            status: 400,
          });
        }
      }
    }
    // else {
    //   const plan = await getPlanQuota(user.team!);
    //   for (const file of files) {
    //     if (Number(file.size) > Number(plan.stMaxFileSize)) {
    //       return Response.json(`File (${file.name}) size limit exceeded`, {
    //         status: 400,
    //       });
    //     }
    //   }
    // }

    // 检查存储桶容量限制
    const totalUploadSize = files.reduce(
      (sum, file) => sum + Number(file.size),
      0,
    );

    if (bucketConfig?.max_storage) {
      const bucketUsage = await getBucketStorageUsage(
        bucket,
        provider,
        user.id,
      );
      if (bucketUsage.success && bucketUsage.data) {
        const currentUsage = bucketUsage.data.totalSize;
        const maxStorage = Number(bucketConfig.max_storage);

        if (currentUsage + totalUploadSize > maxStorage) {
          const remainingSpace = maxStorage - currentUsage;
          const remainingSpaceGB = (
            remainingSpace /
            (1024 * 1024 * 1024)
          ).toFixed(2);
          return Response.json(
            `Bucket storage limit exceeded. Remaining space: ${remainingSpaceGB} GB.`,
            { status: 403 },
          );
        }
      }
    }

    const R2 = createS3Client(
      providerChannel.endpoint,
      providerChannel.access_key_id,
      providerChannel.secret_access_key,
    );

    const signedUrls = await Promise.all(
      files.map(async (file: { name: string; type: string; size: number }) => {
        const fileName = generateFileKey(file.name, prefix || "");

        const signedUrl = await getSignedUrl(
          R2,
          new PutObjectCommand({
            Bucket: bucket,
            Key: fileName,
            ContentType: file.type,
            ContentLength: file.size,
          }),
          { expiresIn: 600 }, // 10分钟过期时间
        );

        return {
          originalName: file.name,
          fileName,
          url: signedUrl,
          type: file.type,
          size: file.size,
        };
      }),
    );

    return NextResponse.json({ urls: signedUrls });
  } catch (error) {
    console.error("生成预签名 URL 失败:", error);
    return NextResponse.json({ error: "Server Error" }, { status: 500 });
  }
}

// Get download url
export async function GET(request: NextRequest) {
  try {
    const user = checkUserStatus(await getCurrentUser());
    if (user instanceof Response) return user;

    const url = new URL(request.url);
    const path = url.searchParams.get("path");
    const bucket = url.searchParams.get("bucket");

    if (!path || !bucket) {
      return NextResponse.json("Invalid request parameters", {
        status: 400,
      });
    }

    const configs = await getMultipleConfigs(["s3_config_01"]);
    if (!configs.s3_config_01.enabled) {
      return NextResponse.json("S3 is not enabled", {
        status: 403,
      });
    }
    if (
      !configs.s3_config_01 ||
      !configs.s3_config_01.access_key_id ||
      !configs.s3_config_01.secret_access_key ||
      !configs.s3_config_01.endpoint
    ) {
      return NextResponse.json("Invalid S3 config", {
        status: 403,
      });
    }
    const buckets = configs.s3_config_01.buckets || [];
    if (!buckets.find((b) => b.bucket === bucket)) {
      return NextResponse.json("Bucket does not exist", {
        status: 403,
      });
    }

    const R2 = createS3Client(
      configs.s3_config_01.endpoint,
      configs.s3_config_01.access_key_id,
      configs.s3_config_01.secret_access_key,
    );

    const pre_url = await getSignedUrl(
      R2,
      new GetObjectCommand({
        Bucket: bucket,
        Key: path,
      }),
      {
        expiresIn: 600,
      },
    );
    return Response.json({ url: pre_url });
  } catch (error: any) {
    return Response.json({ error: error.message });
  }
}
