// 用户配置区域开始 =================================

// GitLab 节点配置
const GITLAB_CONFIGS = [
  { name: '', id: '', token: '' },  // GitLab 账户1
  { name: '', id: '', token: '' },  // GitLab 账户2
  { name: '', id: '', token: '' },  // GitLab 账户3
  { name: '', id: '', token: '' },  // GitLab 账户4
];

// GitHub 配置,仓库名与 GitLab 的相同,故创建仓库时需要注意一定要对称
const GITHUB_USERNAME = '';  // GitHub 用户名
const GITHUB_PAT = '';  // GitHub 个人访问令牌

// R2 存储配置,没有可以留空不填,但不要删除
const R2_CONFIGS = [
  {
    name: '',  // 帐户1 ID
    accountId: '',  // 帐户1 访问密钥 ID
    accessKeyId: '',  // 帐户1 机密访问密钥
    secretAccessKey: '',  // 帐户1 机密访问密钥
    bucket: '' // 帐户1 R2 存储桶名称
  },
  {
    name: '',  // 帐户2 ID
    accountId: '',  // 帐户2 访问密钥 ID
    accessKeyId: '',  // 帐户2 机密访问密钥
    secretAccessKey: '',  // 帐户2 机密访问密钥
    bucket: '' // 帐户2 R2 存储桶名称
  },
  // 可以添加更多 R2 配置
];

// B2 存储配置,没有可以留空不填,但不要删除
const B2_CONFIGS = [
  {
    name: '',  // 帐户1 名
    endPoint: '',  // 账户1 Endpoint
    keyId: '',  // 账户1 keyID
    applicationKey: '',  // 账户1 applicationKey
    bucket: ''  // 账户1桶名 bucketName
  },
  {
    name: '',  // 帐户2 名
    endPoint: '',  // 账户2 Endpoint
    keyId: '',  // 账户2 keyID
    applicationKey: '',  // 账户2 applicationKey
    bucket: ''  // 账户2桶名 bucketName
  },
  // 可以添加更多 B2 配置
];

// 定义集群访问目录
const DIR = '';

// 定义集群里全部节点连接状态的密码验证,区分大小写(优先使用自定义密码,若为空则使用 GITHUB_PAT)
const CHECK_PASSWORD = '' || GITHUB_PAT;

// GitHub 备份策略
const STRATEGY = 'size'  // 可选 [size (默认) | quantity | 指定节点]; size: 选择容量最少的仓库来存储文件; quantity: 选择文件最少的仓库来存储文件; 指定节点: 比如  pic1 或者 pic2
const DELETE = 'true'  // 可选 [true (默认) | false],已复制到 GitHub 的文件,是否从 R2 删除

// 用户配置区域结束 =================================

// 检查配置是否有效
function hasValidConfig() {
  // 检查 GitHub 配置
  const hasGithub = GITHUB_PAT && GITHUB_USERNAME && GITLAB_CONFIGS &&
                    GITLAB_CONFIGS.length > 0 &&
                    GITLAB_CONFIGS.some(config => config.name && config.id && config.token);

  // 检查 GitLab 配置
  const hasGitlab = GITLAB_CONFIGS &&
                    GITLAB_CONFIGS.length > 0 &&
                    GITLAB_CONFIGS.some(config => config.name && config.id && config.token);

  // 检查 R2 配置
  const hasR2 = R2_CONFIGS &&
                R2_CONFIGS.length > 0 &&
                R2_CONFIGS.some(config =>
                  config.name &&
                  config.accountId &&
                  config.accessKeyId &&
                  config.secretAccessKey &&
                  config.bucket
                );

  // 检查 B2 配置
  const hasB2 = B2_CONFIGS &&
                B2_CONFIGS.length > 0 &&
                B2_CONFIGS.some(config =>
                  config.name &&
                  config.endPoint &&
                  config.keyId &&
                  config.applicationKey &&
                  config.bucket
                );

  return {
    github: hasGithub,
    gitlab: hasGitlab,
    r2: hasR2,
    b2: hasB2
  };
}

// AWS SDK 签名相关函数开始 =================================

// 获取签名URL
async function getSignedUrl(config, method, path, queryParams = {}) {
  const region = config.endPoint ? config.endPoint.split('.')[1] : 'auto';
  const service = 's3';
  const host = config.endPoint || `${config.accountId}.r2.cloudflarestorage.com`;
  const accessKeyId = config.endPoint ? config.keyId : config.accessKeyId;
  const secretKey = config.endPoint ? config.applicationKey : config.secretAccessKey;
  const datetime = new Date().toISOString().replace(/[:-]|\.\d{3}/g, '');
  const date = datetime.substr(0, 8);

  // 确保路径正确编码,但保留斜杠
  const encodedPath = path.split('/')
    .map(segment => encodeURIComponent(segment))
    .join('/');

  // 构建规范请求
  const canonicalHeaders = `host:${host}\nx-amz-content-sha256:UNSIGNED-PAYLOAD\nx-amz-date:${datetime}\n`;
  const signedHeaders = 'host;x-amz-content-sha256;x-amz-date';

  // 按字母顺序排序查询参数
  const sortedParams = Object.keys(queryParams).sort().reduce((acc, key) => {
    acc[key] = queryParams[key];
    return acc;
  }, {});

  const canonicalQueryString = Object.entries(sortedParams)
    .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
    .join('&');

  const canonicalRequest = [
    method,
    '/' + encodedPath,
    canonicalQueryString,
    canonicalHeaders,
    signedHeaders,
    'UNSIGNED-PAYLOAD'
  ].join('\n');

  const stringToSign = [
    'AWS4-HMAC-SHA256',
    datetime,
    `${date}/${region}/${service}/aws4_request`,
    await sha256(canonicalRequest)
  ].join('\n');

  const signature = await getSignature(
    secretKey,
    date,
    region,
    service,
    stringToSign
  );

  const authorization = [
    `AWS4-HMAC-SHA256 Credential=${accessKeyId}/${date}/${region}/${service}/aws4_request`,
    `SignedHeaders=${signedHeaders}`,
    `Signature=${signature}`
  ].join(', ');

  const url = `https://${host}/${encodedPath}${canonicalQueryString ? '?' + canonicalQueryString : ''}`;

  return {
    url,
    headers: {
      'Authorization': authorization,
      'x-amz-content-sha256': 'UNSIGNED-PAYLOAD',
      'x-amz-date': datetime,
      'Host': host
    }
  };
}

// SHA256 哈希函数
async function sha256(message) {
  const msgBuffer = new TextEncoder().encode(message);
  const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
  return Array.from(new Uint8Array(hashBuffer))
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');
}

// HMAC-SHA256 函数
async function hmacSha256(key, message) {
  const keyBuffer = key instanceof ArrayBuffer ? key : new TextEncoder().encode(key);
  const messageBuffer = new TextEncoder().encode(message);

  const cryptoKey = await crypto.subtle.importKey(
    'raw',
    keyBuffer,
    { name: 'HMAC', hash: 'SHA-256' },
    false,
    ['sign']
  );

  const signature = await crypto.subtle.sign(
    'HMAC',
    cryptoKey,
    messageBuffer
  );

  return signature;
}

// 获取签名
async function getSignature(secret, date, region, service, stringToSign) {
  const kDate = await hmacSha256('AWS4' + secret, date);
  const kRegion = await hmacSha256(kDate, region);
  const kService = await hmacSha256(kRegion, service);
  const kSigning = await hmacSha256(kService, 'aws4_request');
  const signature = await hmacSha256(kSigning, stringToSign);

  return Array.from(new Uint8Array(signature))
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');
}

// AWS SDK 签名相关函数结束 =================================

// 检查服务函数
async function getGitHubUsername(pat) {
  const url = 'https://api.github.com/user';
  try {
    const response = await fetch(url, {
      headers: {
        'Authorization': `token ${pat}`,
        'Accept': 'application/vnd.github.v3+json',
        'User-Agent': 'Cloudflare Worker'
      }
    });

    if (response.status === 200) {
      const data = await response.json();
      return data.login;
    } else {
      console.error('GitHub API Error:', response.status);
      return 'Unknown';
    }
  } catch (error) {
    console.error('GitHub request error:', error);
    return 'Error';
  }
}

// 修改文件路径处理函数
function getFilePath(basePath, requestPath) {
  // 移除开头的斜杠
  const cleanRequestPath = requestPath.replace(/^\//, '');

  // 如果没有设置 basePath,直接返回请求路径
  if (!basePath) return cleanRequestPath;

  // 组合基础路径和请求路径
  return `${basePath}/${cleanRequestPath}`;
}

// 检查 GitHub 仓库
async function checkGitHubRepo(owner, repo, pat) {
  const repoUrl = `https://api.github.com/repos/${owner}/${repo}`;

  const headers = {
    'Authorization': `token ${pat}`,
    'Accept': 'application/vnd.github.v3+json',
    'User-Agent': 'Cloudflare Worker'
  };

  try {
    // 获取仓库信息,确定默认分支
    const repoResponse = await fetch(repoUrl, { headers });
    const repoData = await repoResponse.json();

    if (repoResponse.status!== 200) {
      throw new Error(`Repository error: ${repoData.message}`);
    }

    const defaultBranch = repoData.default_branch;
    const contentsUrl = `https://api.github.com/repos/${owner}/${repo}/git/trees/${defaultBranch}?recursive=1`;

    // 获取文件树信息
    const contentsResponse = await fetch(contentsUrl, { headers });
    if (contentsResponse.status!== 200) {
      const contentsErrorData = await contentsResponse.json();
      throw new Error(`Contents error: ${contentsErrorData.message}`);
    }

    const contentsData = await contentsResponse.json();

    let fileCount = 0;
    let totalSize = 0;

    if (contentsData.tree) {
      for (const item of contentsData.tree) {
        // 检查是否是文件
        if (item.type === 'blob' && (DIR === '' || item.path.startsWith(DIR + '/'))) {
          fileCount++;
          totalSize += item.size || 0;
        }
      }
    }

    return [
      `working (${repoData.private ? 'private' : 'public'})`,
      fileCount,
      totalSize
    ];

  } catch (error) {
    console.error(`Error checking GitHub repo ${repo}:`, error);
    return [`error: ${error.message}`, 0, 0];
  }
}

// 检查 GitLab 项目
async function checkGitLabProject(projectId, pat) {
  const projectUrl = `https://gitlab.com/api/v4/projects/${projectId}`;
  const treeUrl = `https://gitlab.com/api/v4/projects/${projectId}/repository/tree?recursive=true&per_page=100&path=${DIR}`;

  try {
    const [projectResponse, treeResponse] = await Promise.all([
      fetch(projectUrl, {
        headers: { 'PRIVATE-TOKEN': pat }
      }),
      fetch(treeUrl, {
        headers: { 'PRIVATE-TOKEN': pat }
      })
    ]);

    if (projectResponse.status === 200) {
      const projectData = await projectResponse.json();
      let fileCount = 0;

      if (treeResponse.status === 200) {
        const treeData = await treeResponse.json();
        // 只计算文件,不计算目录
        fileCount = treeData.filter(item => item.type === 'blob').length;
      }

      return [
        `working (${projectData.visibility})`,
        projectData.owner.username,
        fileCount
      ];
    } else if (projectResponse.status === 404) {
      return ['not found', 'Unknown', 0];
    } else {
      return ['disconnect', 'Unknown', 0];
    }
  } catch (error) {
    console.error('GitLab project check error:', error);
    return ['disconnect', 'Error', 0];
  }
}

// 检查 R2 存储
async function checkR2Storage(r2Config) {
  try {
    // 列出所有文件
    const listRequest = await getSignedUrl(r2Config, 'GET', r2Config.bucket, {
      'list-type': '2',
      'prefix': DIR ? `${DIR}/` : ''  // 添加目录前缀筛选
    });

    const response = await fetch(listRequest.url, {
      headers: {
        ...listRequest.headers,
        'Host': `${r2Config.accountId}.r2.cloudflarestorage.com`
      }
    });

    let fileCount = 0;
    let totalSize = 0;

    if (response.ok) {
      const data = await response.text();

      // 使用正则表达式匹配所有文件信息
      const contents = data.match(/<Contents>[\s\S]*?<\/Contents>/g) || [];

      for (const content of contents) {
        const keyMatch = content.match(/<Key>([^<]+)<\/Key>/);
        const sizeMatch = content.match(/<Size>(\d+)<\/Size>/);

        if (keyMatch && sizeMatch) {
          const key = keyMatch[1];
          // 只计算文件,不计算目录
          if (!key.endsWith('/')) {
            fileCount++;
            totalSize += parseInt(sizeMatch[1]);
          }
        }
      }
    }

    return [
      'working',
      r2Config.name,
      r2Config.bucket,
      fileCount,
      formatSize(totalSize)
    ];
  } catch (error) {
    console.error('R2 Storage error:', error);
    return ['error', r2Config.name, 'connection failed', 0, '0 B'];
  }
}

// 检查 B2 存储
async function checkB2Storage(b2Config) {
  try {
    // 构建列出文件的请求,移除 delimiter 参数以获取所有子目录
    const signedRequest = await getSignedUrl(b2Config, 'GET', b2Config.bucket, {
      'prefix': DIR ? `${DIR}/` : ''
    });

    const response = await fetch(signedRequest.url, {
      headers: {
        ...signedRequest.headers,
        'Host': b2Config.endPoint
      }
    });

    let fileCount = 0;
    let totalSize = 0;

    if (response.ok) {
      const data = await response.text();
      // 使用正则表达式匹配所有文件信息
      const keyRegex = /<Key>([^<]+)<\/Key>/g;
      const sizeRegex = /<Size>(\d+)<\/Size>/g;

      let keyMatch;
      while ((keyMatch = keyRegex.exec(data)) !== null) {
        const key = keyMatch[1];
        // 只计算文件,不计算目录,并确保文件在指定目录下
        if (!key.endsWith('/') && (!DIR || key.startsWith(DIR + '/'))) {
          fileCount++;
          // 获取对应的文件大小
          const sizeMatch = /<Size>(\d+)<\/Size>/g.exec(data.slice(keyMatch.index));
          if (sizeMatch) {
            totalSize += parseInt(sizeMatch[1]);
          }
        }
      }

      return [
        'working',
        b2Config.name,
        b2Config.bucket,
        fileCount,
        formatSize(totalSize)
      ];
    } else {
      throw new Error(`Failed to list bucket: ${response.status} ${response.statusText}`);
    }

  } catch (error) {
    console.error('B2 Storage error:', error);
    return ['error', b2Config.name, b2Config.bucket, 0, '0 B'];
  }
}

// 删除 GitHub 仓库中的文件
async function deleteGitHubFile(repo, filePath, pat) {
  // 构建完整的文件路径,包含 DIR
  const fullPath = DIR ? `${DIR}/${filePath.replace(/^\/+/, '')}` : filePath.replace(/^\/+/, '');
  const url = `https://api.github.com/repos/${GITHUB_USERNAME}/${repo}/contents/${fullPath}`;

  try {
    // 先检查文件是否存在
    const getResponse = await fetch(url, {
      headers: {
        'Authorization': `token ${pat}`,
        'Accept': 'application/vnd.github.v3+json',
        'User-Agent': 'Cloudflare Worker'
      }
    });

    if (getResponse.status === 404) {
      return '文件不存在';
    }

    if (!getResponse.ok) {
      const errorData = await getResponse.json();
      return `删除失败:(${errorData.message})`;
    }

    const fileData = await getResponse.json();

    // 执行删除操作
    const deleteResponse = await fetch(url, {
      method: 'DELETE',
      headers: {
        'Authorization': `token ${pat}`,
        'Accept': 'application/vnd.github.v3+json',
        'User-Agent': 'Cloudflare Worker'
      },
      body: JSON.stringify({
        message: `Delete ${fullPath}`,
        sha: fileData.sha
      })
    });

    if (deleteResponse.ok) {
      return '删除成功';
    } else {
      const errorData = await deleteResponse.json();
      return `删除失败:(${errorData.message})`;
    }
  } catch (error) {
    console.error('GitHub delete error:', error);
    return `删除失败:(${error.message})`;
  }
}

// 删除 GitLab 项目中的文件
async function deleteGitLabFile(projectId, filePath, pat) {
  // 构建完整的文件路径,包含 DIR
  const fullPath = DIR ? `${DIR}/${filePath.replace(/^\/+/, '')}` : filePath.replace(/^\/+/, '');
  const encodedPath = encodeURIComponent(fullPath);
  const url = `https://gitlab.com/api/v4/projects/${projectId}/repository/files/${encodedPath}`;

  try {
    // 执行删除操作
    const deleteResponse = await fetch(url, {
      method: 'DELETE',
      headers: {
        'PRIVATE-TOKEN': pat,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        branch: 'main',
        commit_message: 'Delete file: ' + fullPath
      })
    });

    // 获取响应数据
    const errorData = await deleteResponse.json().catch(() => ({}));

    // 处理文件不存在的所有可能情况
    if (deleteResponse.status === 404 ||
      errorData.message === 'A file with this name doesn\'t exist' ||
      errorData.message?.includes('file does not exist') ||
      errorData.message?.includes('File not found')) {
      return '文件不存在';
    }

    // 处理删除成功的情况
    if (deleteResponse.ok ||
      errorData.message?.includes('reference update') ||
      errorData.message?.includes('reference does not point')) {
      return '删除成功';
    }

    return `删除失败:(${errorData.message || '未知错误'})`;
  } catch (error) {
    console.error('GitLab delete error:', error);
    if (error.message?.includes('file') && error.message?.includes('exist')) {
      return '文件不存在';
    }
    return `删除失败:(${error.message})`;
  }
}

// 删除 R2 存储中的文件
async function deleteR2File(r2Config, filePath) {
  // 构建完整的文件路径,包含 DIR
  const fullPath = DIR ? `${DIR}/${filePath.replace(/^\/+/, '')}` : filePath.replace(/^\/+/, '');

  try {
    // 1. 首先列出所有文件
    const listRequest = await getSignedUrl(r2Config, 'GET', r2Config.bucket, {
      'list-type': '2',
      'prefix': fullPath  // 使用精确的前缀匹配
    });

    const listResponse = await fetch(listRequest.url, {
      headers: {
        ...listRequest.headers,
        'Host': `${r2Config.accountId}.r2.cloudflarestorage.com`
      }
    });

    if (!listResponse.ok) {
      throw new Error(`Failed to list objects: ${listResponse.statusText}`);
    }

    // 解析响应
    const listData = await listResponse.text();
    const contents = listData.match(/<Contents>[\s\S]*?<\/Contents>/g) || [];
    let fileExists = false;

    // 精确匹配文件路径
    for (const content of contents) {
      const keyMatch = content.match(/<Key>([^<]+)<\/Key>/);
      if (keyMatch && keyMatch[1] === fullPath) {
        fileExists = true;
        break;
      }
    }

    if (!fileExists) {
      return '文件不存在';
    }

    // 2. 删除文件
    const deleteRequest = await getSignedUrl(r2Config, 'DELETE', `${r2Config.bucket}/${fullPath}`);

    const deleteResponse = await fetch(deleteRequest.url, {
      method: 'DELETE',
      headers: {
        ...deleteRequest.headers,
        'Host': `${r2Config.accountId}.r2.cloudflarestorage.com`
      }
    });

    if (!deleteResponse.ok) {
      const deleteResponseText = await deleteResponse.text();
      throw new Error(`Failed to delete: ${deleteResponse.status} - ${deleteResponseText}`);
    }

    return '删除成功';
  } catch (error) {
    console.error('R2 delete error:', error);
    return `删除失败:(${error.message})`;
  }
}

// 删除 B2 存储中的文件
async function deleteB2File(b2Config, filePath) {
  // 构建完整的文件路径,包含 DIR
  const fullPath = DIR ? `${DIR}/${filePath.replace(/^\/+/, '')}` : filePath.replace(/^\/+/, '');

  try {
    // 1. 首先列出所有文件
    const listObjectsRequest = await getSignedUrl(b2Config, 'GET', b2Config.bucket, {
      'list-type': '2',
      'prefix': fullPath
    });

    const listResponse = await fetch(listObjectsRequest.url, {
      headers: {
        ...listObjectsRequest.headers,
        'Host': b2Config.endPoint
      }
    });

    if (!listResponse.ok) {
      throw new Error(`Failed to list objects: ${listResponse.statusText}`);
    }

    // 解析 XML 响应
    const listData = await listResponse.text();
    const keyRegex = /<Key>([^<]+)<\/Key>/g;
    const fileExists = Array.from(listData.matchAll(keyRegex))
      .some(match => match[1] === fullPath);

    if (!fileExists) {
      return '文件不存在';
    }

    // 2. 获取文件的版本信息
    const versionsRequest = await getSignedUrl(b2Config, 'GET', b2Config.bucket, {
      'versions': '',
      'prefix': fullPath,
      'list-type': '2'
    });

    const versionsResponse = await fetch(versionsRequest.url, {
      headers: {
        ...versionsRequest.headers,
        'Host': b2Config.endPoint,
        'x-amz-date': versionsRequest.headers['x-amz-date'],
        'Authorization': versionsRequest.headers['Authorization']
      }
    });

    if (!versionsResponse.ok) {
      const responseText = await versionsResponse.text();
      console.error('Version listing response:', responseText);
      throw new Error(`Failed to list versions: ${versionsResponse.status} - ${responseText}`);
    }

    const versionsData = await versionsResponse.text();

    // 解析版本信息
    const versionMatch = versionsData.match(/<Version>[\s\S]*?<VersionId>([^<]+)<\/VersionId>[\s\S]*?<\/Version>/);
    if (!versionMatch) {
      throw new Error('No version information found');
    }

    const versionId = versionMatch[1];

    // 3. 删除指定版本的文件
    const deleteRequest = await getSignedUrl(b2Config, 'DELETE', `${b2Config.bucket}/${fullPath}`, {
      'versionId': versionId
    });

    const deleteResponse = await fetch(deleteRequest.url, {
      method: 'DELETE',
      headers: {
        ...deleteRequest.headers,
        'Host': b2Config.endPoint,
        'x-amz-date': deleteRequest.headers['x-amz-date'],
        'Authorization': deleteRequest.headers['Authorization']
      }
    });

    if (!deleteResponse.ok) {
      const deleteResponseText = await deleteResponse.text();
      throw new Error(`Failed to delete: ${deleteResponse.status} - ${deleteResponseText}`);
    }

    return '删除成功';
  } catch (error) {
    console.error('B2 delete error:', error);
    return `删除失败:(${error.message})`;
  }
}

// 文件大小格式化函数
function formatSize(sizeInBytes) {
  if (sizeInBytes >= 1024 * 1024 * 1024) {
    return `${(sizeInBytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
  } else if (sizeInBytes >= 1024 * 1024) {
    return `${(sizeInBytes / (1024 * 1024)).toFixed(2)} MB`;
  } else {
    return `${(sizeInBytes / 1024).toFixed(2)} kB`;
  }
}

export default {
  async fetch(request, env, ctx) {
    // 获取请求 URL 对象
    const url = new URL(request.url);

    // 从 URL 的查询参数中获取 'from' 参数并转换为小写
    const from = url.searchParams.get('from')?.toLowerCase();

    // 检查是否有有效的配置,调用 `hasValidConfig()` 函数
    const validConfigs = hasValidConfig();

    // 获取请求路径并解码(对 URL 编码进行解码)
    const requestPath = decodeURIComponent(url.pathname);

    // 添加根路径项目介绍
    if (requestPath === '/') {
      return new Response(
        '欢迎来到文件托管集群!(File Hosting Cluster)\n' +
        '这是一个分布式存储集群项目,旨在提供高效的文件存储和管理服务。\n\n' +
        '项目链接: https://github.com/fscarmen2/pic-hosting-cluster\n' +
        '视频介绍: https://youtu.be/5i-86oBLWP8\n\n' +
        '您可以使用以下操作:\n' +
        '1. 从集群所有节点获取文件: /<文件名>\n' +
        '2. 指定从 Github 获取文件: /<文件名>?from=github\n' +
        '3. 指定从 Gitlab 获取文件: /<文件名>?from=gitlab\n' +
        '4. 指定从 Cloudflare R2 获取文件: /<文件名>?from=r2\n' +
        '5. 指定从 Backblaze B2 获取文件: /<文件名>?from=b2\n' +
        '6. 查找文件信息: /<文件名>?from=where\n' +
        '7. 查各节点状态: /<自定义密码>\n' +
        '8. 删除文件: /<自定义密码>/del?file=<文件名>',
        {
          headers: {
            'Content-Type': 'text/plain; charset=UTF-8',
            'Access-Control-Allow-Origin': '*'
          }
        }
      );
    }

    // 从路径中提取文件名(即路径的最后一部分)
    const FILE = requestPath.split('/').pop();

    // 获取子目录路径,移除开头和结尾的斜杠
    const subPath = requestPath.substring(1, requestPath.lastIndexOf('/')).replace(/^\/+|\/+$/g, '');

    // 如果 DIR 存在,拼接 DIR 和子目录路径;否则仅使用子目录路径
    const fullPath = DIR ? `${DIR}/${subPath}` : subPath;

    // 检查请求路径是否匹配删除请求(支持 'delete' 或 'del')
    const isDeleteRequest = requestPath.match(new RegExp(`^/${CHECK_PASSWORD}/(delete|del)$`));

    // 检查是否是未授权的删除请求
    const isUnauthorizedDelete = requestPath.match(/^\/(delete|del)$/);
    if (isUnauthorizedDelete) {
      const file = url.searchParams.get('file');
      if (!file) {
        return new Response(
          '需要指定要删除的文件。\n' +
          '正确的删除格式为: /<自定义密码>/del?file=文件路径\n' +
          '例如: /<自定义密码>/del?file=example.png',
          {
            status: 403,
            headers: {
              'Content-Type': 'text/plain; charset=UTF-8',
              'Access-Control-Allow-Origin': '*'
            }
          }
        );
      }

      return new Response(
        '需要密码验证才能删除文件。\n' +
        '要删除文件 ' + file + ' 的正确格式为:\n' +
        '/<自定义密码>/del?file=' + file,
        {
          status: 403,
          headers: {
            'Content-Type': 'text/plain; charset=UTF-8',
            'Access-Control-Allow-Origin': '*'
          }
        }
      );
    }

    // 从 GITLAB_CONFIGS 中获取每个配置的 name 作为 GitHub 仓库名
    const githubRepos = GITLAB_CONFIGS.map(config => config.name);

    // 只在没有 from 参数时才检查和使用缓存
    let cacheResponse;
    if (!from) {
      const cacheUrl = new URL(request.url);
      const cacheKey = new Request(cacheUrl.toString(), request);
      const cache = caches.default;
      cacheResponse = await cache.match(cacheKey);

      if (cacheResponse) {
        return cacheResponse;
      }
    }

    // 检查状态页面
    if (url.pathname === `/${CHECK_PASSWORD}`) {
      let result = '';
      let hasAnyValidConfig = false;

      try {
        // GitHub 状态检查
        if (validConfigs.github) {
          hasAnyValidConfig = true;
          result += '=== GitHub Status ===\n';
          const username = await getGitHubUsername(GITHUB_PAT);
          for (const repo of githubRepos) {
            const [status, fileCount, totalSize] = await checkGitHubRepo(GITHUB_USERNAME, repo, GITHUB_PAT);
            const formattedSize = formatSize(totalSize);
            result += `GitHub: ${repo} - ${status} (Username: ${username}, Files: ${fileCount}, Size: ${formattedSize})\n`;
          }
        }

        // GitLab 状态检查
        if (validConfigs.gitlab) {
          hasAnyValidConfig = true;
          result += result ? '\n=== GitLab Status ===\n' : '=== GitLab Status ===\n';
          for (const config of GITLAB_CONFIGS) {
            const [status, username, fileCount] = await checkGitLabProject(config.id, config.token);
            result += `GitLab: Project ID ${config.id} - ${status} (Username: ${username}, Files: ${fileCount})\n`;
          }
        }

        // R2 状态检查
        if (validConfigs.r2) {
          hasAnyValidConfig = true;
          result += result ? '\n=== R2 Storage Status ===\n' : '=== R2 Storage Status ===\n';
          for (const config of R2_CONFIGS) {
            const [status, name, bucket, fileCount, totalSize] = await checkR2Storage(config);
            result += `R2 Storage: ${name} - ${status} (Bucket: ${bucket}, Files: ${fileCount}, Size: ${totalSize})\n`;
          }
        }

        // B2 状态检查
        if (validConfigs.b2) {
          hasAnyValidConfig = true;
          result += result ? '\n=== B2 Storage Status ===\n' : '=== B2 Storage Status ===\n';
          for (const config of B2_CONFIGS) {
            const [status, name, bucket, fileCount, totalSize] = await checkB2Storage(config);
            result += `B2 Storage: ${name} - ${status} (Bucket: ${bucket}, Files: ${fileCount}, Size: ${totalSize})\n`;
          }
        }

        // 如果没有任何有效配置
        if (!hasAnyValidConfig) {
          result = 'No storage services configured.\n';
        } else {
          result = 'Storage status:\n\n' + result;
        }

      } catch (error) {
        result += `Error during status check: ${error.message}\n`;
      }

      return new Response(result, {
        headers: {
          'Content-Type': 'text/plain; charset=UTF-8',
          'Access-Control-Allow-Origin': '*'
        }
      });
    }

    // 添加删除路由
    if (isDeleteRequest) {
      const file = url.searchParams.get('file');
      if (!file) {
        return new Response('Missing "file" parameter', {
          status: 400,
          headers: { 'Content-Type': 'text/plain; charset=UTF-8', 'Access-Control-Allow-Origin': '*' }
        });
      }

      let result = `Delete:${file}\n`;

      // GitHub 状态
      if (validConfigs.github) {
        result += '\n=== GitHub Status ===\n';
        const githubRepos = GITLAB_CONFIGS.map(config => config.name);
        for (const repo of githubRepos) {
          const status = await deleteGitHubFile(repo, file, GITHUB_PAT);
          result += `GitHub: ${repo} - working (private) ${status}\n`;
        }
      }

      // GitLab 状态
      if (validConfigs.gitlab) {
        result += '\n=== GitLab Status ===\n';
        for (const config of GITLAB_CONFIGS) {
          const status = await deleteGitLabFile(config.id, file, config.token);
          const projectData = await fetch(`https://gitlab.com/api/v4/projects/${config.id}`, {
            headers: { 'PRIVATE-TOKEN': config.token }
          }).then(res => res.json());
          result += `GitLab: Project ID ${config.id} - working (${projectData.visibility}) ${status}\n`;
        }
      }

      // R2 存储状态
      if (validConfigs.r2) {
        result += '\n=== R2 Storage Status ===\n';
        for (const config of R2_CONFIGS) {
          const status = await deleteR2File(config, file);
          result += `R2 Storage: ${config.name} - working ${status}\n`;
        }
      }

      // B2 存储状态
      if (validConfigs.b2) {
        result += '\n=== B2 Storage Status ===\n';
        for (const config of B2_CONFIGS) {
          const status = await deleteB2File(config, file);
          result += `B2 Storage: ${config.name} - working ${status}\n`;
        }
      }

      return new Response(result, {
        headers: {
          'Content-Type': 'text/plain; charset=UTF-8',
          'Access-Control-Allow-Origin': '*'
        }
      });
    }

    const startTime = Date.now();
    let requests = [];

    // 检查特定服务的请求是否有效
    if (from) {
      if (from === 'github' && !validConfigs.github) {
        return new Response('GitHub service is not configured.', {
          status: 400,
          headers: { 'Content-Type': 'text/plain', 'Access-Control-Allow-Origin': '*' }
        });
      }
      if (from === 'gitlab' && !validConfigs.gitlab) {
        return new Response('GitLab service is not configured.', {
          status: 400,
          headers: { 'Content-Type': 'text/plain', 'Access-Control-Allow-Origin': '*' }
        });
      }
      if (from === 'r2' && !validConfigs.r2) {
        return new Response('R2 storage service is not configured.', {
          status: 400,
          headers: { 'Content-Type': 'text/plain', 'Access-Control-Allow-Origin': '*' }
        });
      }
      if (from === 'b2' && !validConfigs.b2) {
        return new Response('B2 storage service is not configured.', {
          status: 400,
          headers: { 'Content-Type': 'text/plain', 'Access-Control-Allow-Origin': '*' }
        });
      }
    }

    // 生成存储请求
    async function generateStorageRequests() {
      let requests = [];

      // 处理请求路径,保留子目录结构
      const getStoragePath = (filePath) => {
        return filePath.replace(/^\/+/, '').replace(/\/+/g, '/');
      };

      if (validConfigs.r2) {
        const r2Requests = await Promise.all(R2_CONFIGS.map(async (r2Config) => {
          // 构建包含子目录的完整路径
          const storagePath = getStoragePath(`${subPath}/${FILE}`);
          const r2Path = `${r2Config.bucket}/${DIR}/${storagePath}`;

          const signedRequest = await getSignedUrl(r2Config, 'GET', r2Path);
          return {
            url: signedRequest.url,
            headers: {
              ...signedRequest.headers,
              'Accept': '*/*'
            },
            source: 'r2',
            repo: `${r2Config.name} (${r2Config.bucket})`
          };
        }));
        requests = [...requests, ...r2Requests];
      }

      if (validConfigs.b2) {
        const b2Requests = await Promise.all(B2_CONFIGS.map(async (b2Config) => {
          // 构建完整路径,注意 B2 需要包含 bucket 名称
          const storagePath = getStoragePath(`${subPath}/${FILE}`);
          const b2Path = `${b2Config.bucket}/${DIR}/${storagePath}`;

          const signedRequest = await getSignedUrl({
            endPoint: b2Config.endPoint,
            keyId: b2Config.keyId,
            applicationKey: b2Config.applicationKey,
            bucket: b2Config.bucket
          }, 'GET', b2Path);

          return {
            url: signedRequest.url,
            headers: {
              ...signedRequest.headers,
              'Host': b2Config.endPoint,
              'Accept': '*/*'
            },
            source: 'b2',
            repo: `${b2Config.name} (${b2Config.bucket})`
          };
        }));
        requests = [...requests, ...b2Requests];
      }

      return requests;
    }

    // 处理不同类型的请求
    if (from === 'where') {
      if (validConfigs.github) {
        const githubRequests = githubRepos.map(repo => ({
          url: `https://api.github.com/repos/${GITHUB_USERNAME}/${repo}/contents/${getFilePath(DIR, `${subPath}/${FILE}`)}`,
          headers: {
            'Authorization': `token ${GITHUB_PAT}`,
            'Accept': 'application/vnd.github.v3+json',
            'User-Agent': 'Cloudflare Worker'
          },
          source: 'github',
          repo: repo,
          processResponse: async (response) => {
            if (!response.ok) throw new Error('Not found');
            const data = await response.json();
            return {
              size: data.size,
              exists: true
            };
          }
        }));
        requests = [...requests, ...githubRequests];
      }

      if (validConfigs.gitlab) {
        const gitlabRequests = GITLAB_CONFIGS.map(config => ({
          // GitLab where 查询 URL
          url: `https://gitlab.com/api/v4/projects/${config.id}/repository/files/${encodeURIComponent(getFilePath(DIR, `${subPath}/${FILE}`))}?ref=main`,
          headers: {
            'PRIVATE-TOKEN': config.token
          },
          source: 'gitlab',
          repo: config.name,
          processResponse: async (response) => {
            if (!response.ok) throw new Error('Not found');
            const data = await response.json();
            return {
              size: data.size,
              exists: true
            };
          }
        }));
        requests = [...requests, ...gitlabRequests];
      }

      const storageRequests = await generateStorageRequests();
      const storageWhereRequests = storageRequests.map(request => ({
        ...request,
        processResponse: async (response) => {
          if (!response.ok) throw new Error('Not found');
          const size = response.headers.get('content-length');
          return {
            size: parseInt(size),
            exists: true
          };
        }
      }));
      requests = [...requests, ...storageWhereRequests];

    } else {
      // 获取文件内容模式
      if (from === 'github' && validConfigs.github) {
        requests = githubRepos.map(repo => ({
          url: `https://raw.githubusercontent.com/${GITHUB_USERNAME}/${repo}/main/${fullPath}/${FILE}`,
          headers: {
            'Authorization': `token ${GITHUB_PAT}`,
            'User-Agent': 'Cloudflare Worker'
          },
          source: 'github',
          repo: repo
        }));
      } else if (from === 'gitlab' && validConfigs.gitlab) {
        requests = GITLAB_CONFIGS.map(config => ({
          // GitLab 文件获取 URL
          url: `https://gitlab.com/api/v4/projects/${config.id}/repository/files/${encodeURIComponent(getFilePath(DIR, `${subPath}/${FILE}`))}/raw?ref=main`,
          headers: {
            'PRIVATE-TOKEN': config.token
          },
          source: 'gitlab',
          repo: config.name
        }));
      } else if ((from === 'r2' && validConfigs.r2) || (from === 'b2' && validConfigs.b2)) {
        requests = await generateStorageRequests();
        requests = requests.filter(req => req.source === from);
      } else if (!from) {
        if (validConfigs.github) {
          const githubRequests = githubRepos.map(repo => ({
            url: `https://raw.githubusercontent.com/${GITHUB_USERNAME}/${repo}/main/${fullPath}/${FILE}`,
            headers: {
              'Authorization': `token ${GITHUB_PAT}`,
              'User-Agent': 'Cloudflare Worker'
            },
            source: 'github',
            repo: repo
          }));
          requests = [...requests, ...githubRequests];
        }

        if (validConfigs.gitlab) {
          const gitlabRequests = GITLAB_CONFIGS.map(config => ({
            // GitLab URL 构建方式
            url: `https://gitlab.com/api/v4/projects/${config.id}/repository/files/${encodeURIComponent(getFilePath(DIR, `${subPath}/${FILE}`))}/raw?ref=main`,
            headers: {
              'PRIVATE-TOKEN': config.token
            },
            source: 'gitlab',
            repo: config.name
          }));
          requests = [...requests, ...gitlabRequests];
        }

        const storageRequests = await generateStorageRequests();
        requests = [...requests, ...storageRequests];
      }
    }

    // 处理请求和响应
    try {
      if (requests.length === 0) {
        throw new Error('No valid source specified or no valid configurations found');
      }

      const fetchPromises = requests.map(request => {
        const { url, headers, source, repo, processResponse } = request;

        return fetch(new Request(url, {
          method: 'GET',
          headers: headers
        })).then(async response => {
          if (from === 'where' && typeof processResponse === 'function') {
            try {
              const result = await processResponse(response);
              const endTime = Date.now();
              const duration = endTime - startTime;

              const formattedSize = result.size > 1024 * 1024
                ? `${(result.size / (1024 * 1024)).toFixed(2)} MB`
                : `${(result.size / 1024).toFixed(2)} kB`;

              return {
                fileName: FILE,
                size: formattedSize,
                source: `${source} (${repo})`,
                duration: `${duration}ms`
              };
            } catch (error) {
              throw new Error(`Not found in ${source} (${repo})`);
            }
          } else {
            if (!response.ok) {
              throw new Error(`Not found in ${source} (${repo})`);
            }
            return response;
          }
        }).catch(error => {
          throw new Error(`Error in ${source} (${repo}): ${error.message}`);
        });
      });

      const result = await Promise.any(fetchPromises);

      let response;
      if (from === 'where') {
        response = new Response(JSON.stringify(result, null, 2), {
          headers: {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Origin': '*'
          }
        });
      } else if (result instanceof Response) {
        const blob = await result.blob();
        const headers = {
          'Content-Type': result.headers.get('Content-Type') || 'application/octet-stream',
          'Access-Control-Allow-Origin': '*'
        };

        if (from) {
          headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, proxy-revalidate';
          headers['Pragma'] = 'no-cache';
          headers['Expires'] = '0';
        }

        response = new Response(blob, {
          status: 200,
          headers: headers
        });
      } else {
        throw new Error("Unexpected result type");
      }

      if (!from && from !== 'where') {
        const cacheUrl = new URL(request.url);
        const cacheKey = new Request(cacheUrl.toString(), request);
        const cache = caches.default;
        ctx.waitUntil(cache.put(cacheKey, response.clone()));
      }

      return response;

    } catch (error) {
      const sourceText = from === 'where'
        ? 'in any repository'
        : from
          ? `from ${from}`
          : 'in any configured storage';

      const errorResponse = new Response(
        `404: Cannot find ${FILE} ${sourceText}. ${error.message}`,
        {
          status: 404,
          headers: {
            'Content-Type': 'text/plain',
            'Access-Control-Allow-Origin': '*'
          }
        }
      );

      return errorResponse;
    }
  }
}