// import { s3A, awsBucketName, awsRegion, awsSecretAccessKey } from "@/src/lib/env-exporter"
import type { Buffer } from 'buffer'
import { DeleteObjectCommand, DeleteObjectsCommand, PutObjectCommand, S3Client, GetObjectCommand } from "@aws-sdk/client-s3"
import { getSignedUrl } from "@aws-sdk/s3-request-presigner"
// import signedUrlCache from "@/src/lib/signed-url-cache" // Disabled for Workers compatibility
import { claimUploadUrlStatus, createUploadUrlStatus } from '@/src/dbService'
import {
  getS3AccessKeyId,
  getS3Region,
  getS3Url,
  getS3SecretAccessKey,
  getS3BucketName,
  getAssetsDomain,
} from "@/src/lib/env-exporter"

let s3Client: S3Client | null = null
let s3ClientKey = ''

const getS3Client = () => {
  const region = getS3Region()
  const endpoint = getS3Url()
  const accessKeyId = getS3AccessKeyId()
  const secretAccessKey = getS3SecretAccessKey()
  const nextKey = `${region}|${endpoint}|${accessKeyId}|${secretAccessKey}`

  if (!s3Client || nextKey !== s3ClientKey) {
    s3ClientKey = nextKey
    s3Client = new S3Client({
      region,
      endpoint,
      forcePathStyle: true,
      credentials: {
        accessKeyId,
        secretAccessKey,
      },
    })
  }

  return s3Client
}

// export const imageUploadS3 = async(body: Buffer, type: string, key:string) => {
//   // const key = `${category}/${Date.now()}`
//   const s3BucketName = getS3BucketName()
//   const s3Client = getS3Client()
//   const command = new PutObjectCommand({
//     Bucket: s3BucketName,
//     Key: key,
//     Body: body,
//     ContentType: type,
//   })
//   const resp = await s3Client.send(command)
//   
//   const imageUrl = `${key}`
//   return imageUrl;
// }

export const imageUploadS3 = async(body: Buffer, type: string, key:string) => {
  const env = (globalThis as any).ENV || {}
  if (!env.MY_BUCKET) {
    throw new Error('MY_BUCKET binding not found in runtime env')
  }
  await env.MY_BUCKET.put(key, body, {
    httpMetadata: {
      contentType: type,
    },
  })
  const imageUrl = `${key}`
  return imageUrl
}


// export async function deleteImageUtil(...keys:string[]):Promise<boolean>;

export async function deleteImageUtil({bucket = getS3BucketName(), keys}:{bucket?:string, keys: string[]}) {
  
  if (keys.length === 0) {
    return true;
  }
  try {
    const s3Client = getS3Client()
    await Promise.all(
      keys.map((key) => {
        const deleteCommand = new DeleteObjectCommand({
          Bucket: bucket,
          Key: key,
        })
        return s3Client.send(deleteCommand)
      })
    )
    return true
  }
  catch (error) {
    console.error("Error deleting image:", error)
    throw new Error("Failed to delete image")
  }
}

export function scaffoldAssetUrl(input: string | null): string
export function scaffoldAssetUrl(input: (string | null)[]): string[]
export function scaffoldAssetUrl(input: string | null | (string | null)[]): string | string[] {
  const assetsDomain = getAssetsDomain()
  if (Array.isArray(input)) {
    return input.map(key => scaffoldAssetUrl(key) as string);
  }
  if (!input) {
    return '';
  }
  const normalizedKey = input.replace(/^\/+/, '');
  const domain = assetsDomain.endsWith('/')
    ? assetsDomain.slice(0, -1)
    : assetsDomain;
  return `${domain}/${normalizedKey}`;
}


/**
 * Generate a signed URL from an S3 URL
 * @param s3Url The full S3 URL (e.g., https://bucket-name.s3.region.amazonaws.com/path/to/object)
 * @param expiresIn Expiration time in seconds (default: 259200 seconds = 3 days)
 * @returns A pre-signed URL that provides temporary access to the object
 */
export async function generateSignedUrlFromS3Url(s3UrlRaw: string|null, expiresIn: number = 259200): Promise<string> {
  if (!s3UrlRaw) {
    return '';
  }

  const s3Url = s3UrlRaw
  
  try {
    // Cache disabled for Workers compatibility
    // const cachedUrl = signedUrlCache.get(s3Url);
    // if (cachedUrl) {
    //   return cachedUrl;
    // }
    
    // Create the command to get the object
    const command = new GetObjectCommand({
      Bucket: getS3BucketName(),
      Key: s3Url,
    });
    
    // Generate the signed URL
    const signedUrl = await getSignedUrl(getS3Client(), command, { expiresIn });
    
    // Cache disabled for Workers compatibility
    // signedUrlCache.set(s3Url, signedUrl, (expiresIn * 1000) - 60000);
    
    return signedUrl;
  } catch (error) {
    console.error("Error generating signed URL:", error);
    throw new Error("Failed to generate signed URL");
  }
}

/**
 * Get the original S3 URL from a signed URL
 * @param signedUrl The signed URL 
 * @returns The original S3 URL if found in cache, otherwise null
 */
export function getOriginalUrlFromSignedUrl(signedUrl: string|null): string|null {
  // Cache disabled for Workers compatibility - cannot retrieve original URL without cache
  // To re-enable, migrate signed-url-cache to object storage (R2/S3)
  return null;
}

/**
 * Generate signed URLs for multiple S3 URLs
 * @param s3Urls Array of S3 URLs or null values
 * @param expiresIn Expiration time in seconds (default: 259200 seconds = 3 days)
 * @returns Array of signed URLs (empty strings for null/invalid inputs)
 */
export async function generateSignedUrlsFromS3Urls(s3Urls: (string|null)[], expiresIn: number = 259200): Promise<string[]> {
  if (!s3Urls || !s3Urls.length) {
    return [];
  }

  try {
    // Process URLs in parallel for better performance
    const signedUrls = await Promise.all(
      s3Urls.map(url => generateSignedUrlFromS3Url(url, expiresIn).catch(() => ''))
    );
    
    return signedUrls;
  } catch (error) {
    console.error("Error generating multiple signed URLs:", error);
    // Return an array of empty strings with the same length as input
    return s3Urls.map(() => '');
  }
}

export async function generateUploadUrl(key: string, mimeType: string, expiresIn: number = 180): Promise<string> {
  try {
    // Insert record into upload_url_status
    await createUploadUrlStatus(key)

    // Generate signed upload URL
    const command = new PutObjectCommand({
      Bucket: getS3BucketName(),
      Key: key,
      ContentType: mimeType,
    });

    const signedUrl = await getSignedUrl(getS3Client(), command, { expiresIn });
    return signedUrl;
  } catch (error) {
    console.error('Error generating upload URL:', error);
    throw new Error('Failed to generate upload URL');
  }
}


// export function extractKeyFromPresignedUrl(url:string) {
//   const u = new URL(url);
//   const rawKey = u.pathname.replace(/^\/+/, ""); // remove leading slash
//   return decodeURIComponent(rawKey);
// }

// New function (excludes bucket name)
export function extractKeyFromPresignedUrl(url: string): string {
  const u = new URL(url);
  const rawKey = u.pathname.replace(/^\/+/, ""); // remove leading slash
  const decodedKey = decodeURIComponent(rawKey);
  // Remove bucket prefix
  const parts = decodedKey.split('/');
  parts.shift(); // Remove bucket name
  return parts.join('/');
}

export async function claimUploadUrl(url: string): Promise<void> {
  try {
    const semiKey = extractKeyFromPresignedUrl(url);

    // Update status to 'claimed' if currently 'pending'
    const updated = await claimUploadUrlStatus(semiKey)
    
    if (!updated) {
      throw new Error('Upload URL not found or already claimed');
    }
  } catch (error) {
    console.error('Error claiming upload URL:', error);
    throw new Error('Failed to claim upload URL');
  }
}
