const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
const path = require('path');
const { convertTsDeclareContentToXml } = require('./TsDeclareToXml');

const DEFAULT_TIMEOUT = 30000;
const MAX_RETRIES = 3;
const RETRY_DELAY = 1000;

// ANSI 颜色代码
const COLORS = {
  reset: '\x1b[0m',
  red: '\x1b[31m',
  green: '\x1b[32m',
  yellow: '\x1b[33m',
  blue: '\x1b[34m',
  magenta: '\x1b[35m',
  cyan: '\x1b[36m',
  bold: '\x1b[1m',
  dim: '\x1b[2m'
};

// 日志工具函数
const logger = {
  // 成功信息（绿色）
  success: (msg) => console.log(`${COLORS.green}[✓] ${msg}${COLORS.reset}`),
  
  // 错误信息（红色加粗）
  error: (msg) => console.error(`${COLORS.red}${COLORS.bold}[✗] ${msg}${COLORS.reset}`),
  
  // 警告信息（黄色）
  warn: (msg) => console.warn(`${COLORS.yellow}[!] ${msg}${COLORS.reset}`),
  
  // 普通信息（蓝色）
  info: (msg) => console.log(`${COLORS.blue}[i] ${msg}${COLORS.reset}`),
  
  // 重要信息（青色加粗）
  important: (msg) => console.log(`${COLORS.cyan}${COLORS.bold}▶ ${msg}${COLORS.reset}`),
  
  // 分隔线
  separator: (msg) => console.log(`\n${COLORS.bold}${COLORS.magenta}═══════════════════════════════════════════\n  ${msg}\n═══════════════════════════════════════════${COLORS.reset}`),
  
  // 调试信息（灰色，默认不显示）
  debug: (msg) => {
    if (process.env.DEBUG) {
      console.log(`${COLORS.dim}[DEBUG] ${msg}${COLORS.reset}`);
    }
  }
};

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function withRetry(fn, maxRetries = MAX_RETRIES, retryDelay = RETRY_DELAY) {
  let lastError;
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      lastError = error;
      logger.warn(`操作失败，${i + 1}/${maxRetries} 次重试... ${error.message}`);
      if (i < maxRetries - 1) {
        await sleep(retryDelay);
      }
    }
  }
  throw lastError;
}

// 从package.json中读取配置
function loadConfig() {
  const packageJsonPath = path.join(__dirname, '../../package.json');
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
  const uploadConfig = packageJson.uploadConfig || {};
  
  // 自动获取当前项目的src路径
  const projectRoot = path.join(__dirname, '../..');
  
  return {
    cloudUrl: uploadConfig.cloudUrl || 'https://me.keytop.cn/fms-webide-server/getProjectTree',
    tryLockUrl: uploadConfig.tryLockUrl || 'https://me.keytop.cn/fms-webide-server/tryLock',
    saveDraftUrl: uploadConfig.saveDraftUrl || 'https://me.keytop.cn/fms-webide-server/saveDraft',
    commitFileUrl: uploadConfig.commitFileUrl || 'https://me.keytop.cn/fms-webide-server/commitFile',
    createLocalLibUrl: uploadConfig.createLocalLibUrl || 'https://me.keytop.cn/fms-webide-server/createLocalLib',
    createServicesUrl: uploadConfig.createServicesUrl || 'https://me.keytop.cn/fms-webide-server/createService',
    createFolderUrl: uploadConfig.createFolderUrl || 'https://me.keytop.cn/fms-webide-server/createFileFolder/v2',
    removeServices: uploadConfig.removeServices || 'https://me.keytop.cn/fms-webide-server/removeService',
    removeServicesFolder: uploadConfig.removeServicesFolder || 'https://me.keytop.cn/fms-webide-server/removeFileFolder',
    removeLocalLib: uploadConfig.removeLocalLib || 'https://me.keytop.cn/fms-webide-server/removeLocalLib',
    projectVersionId: uploadConfig.projectVersionId || '',
    headers: {
      authorization: uploadConfig.authorization || ''
    },
    localRoot: path.join(projectRoot, 'src')
  };
}

const config = loadConfig();

function loadSharedLibConfig() {
  const packageJsonPath = path.join(__dirname, '../../package.json');
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
  const uploadCfg = packageJson.uploadConfig || {};
  return {
    getListUrl:
      uploadCfg.sharedLibGetListUrl ||
      uploadCfg.getListUrl ||
      'https://me.keytop.cn/fms-webide-server/getList',
    addUrl:
      uploadCfg.sharedLibAddUrl ||
      uploadCfg.addUrl ||
      'https://me.keytop.cn/fms-webide-server/add',
    managerUrl:
      uploadCfg.sharedLibManagerUrl ||
      uploadCfg.managerUrl ||
      'https://me.keytop.cn/sharedlib-console/project/manager',
    versionsUrl:
      uploadCfg.sharedLibVersionsUrl ||
      uploadCfg.versionsUrl ||
      'https://me.keytop.cn/sharedlib-console/project/manager/versions',
    projectVersionId: uploadCfg.projectVersionId || '',
    libs: Array.isArray(uploadCfg.sharedLibs)
      ? uploadCfg.sharedLibs
      : Array.isArray(uploadCfg.libs)
        ? uploadCfg.libs
        : [],
    headers: {
      authorization: uploadCfg.authorization || ''
    }
  };
}

function loadThirdLibConfig() {
  const packageJsonPath = path.join(__dirname, '../../package.json');
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
  const uploadCfg = packageJson.uploadConfig || {};
  return {
    getListUrl:
      uploadCfg.thirdLibGetListUrl ||
      'https://me.keytop.cn/fms-webide-server/use/getThirdLib',
    addUrl:
      uploadCfg.thirdLibAddUrl ||
      'https://me.keytop.cn/fms-webide-server/use/addThirdLib',
    projectVersionId: uploadCfg.projectVersionId || '',
    libs: Array.isArray(uploadCfg.thirdLibs)
      ? uploadCfg.thirdLibs
      : [],
    headers: {
      authorization: uploadCfg.authorization || ''
    }
  };
}

function parseVersionNo(versionNo) {
  const text = `${versionNo || ''}`.trim();
  const pure = text.split('-')[0];
  const parts = pure.split('.').map(n => Number(n) || 0);
  return [
    parts[0] || 0,
    parts[1] || 0,
    parts[2] || 0
  ];
}

function compareVersionDesc(a, b) {
  const va = parseVersionNo(a);
  const vb = parseVersionNo(b);
  for (let i = 0; i < 3; i += 1) {
    if (va[i] !== vb[i]) {
      return vb[i] - va[i];
    }
  }
  return 0;
}

async function queryLibProjectIdByPid(sharedCfg, pid) {
  const response = await axios.get(sharedCfg.managerUrl, {
    headers: sharedCfg.headers,
    params: {
      pageNum: 1,
      pageSize: 10,
      serviceCenterId: '',
      appId: '',
      keyword: pid
    }
  });
  const body = response.data || {};
  if (body.code !== '2000' || body.success !== true) {
    throw new Error(`查询共享库项目失败: ${pid} ${body.message || body.msg || body.code}`);
  }
  const list = body?.data?.data || [];
  if (!Array.isArray(list) || !list.length) {
    throw new Error(`未查询到共享库项目: ${pid}`);
  }
  const matched = list.find(item => item.pid === pid) || list[0];
  if (!matched?.projectId) {
    throw new Error(`共享库项目缺少projectId: ${pid}`);
  }
  return matched.projectId;
}

async function queryLatestLibVersionId(sharedCfg, projectId, pid) {
  const response = await axios.get(sharedCfg.versionsUrl, {
    headers: sharedCfg.headers,
    params: {
      projectId
    }
  });
  const body = response.data || {};
  if (body.code !== '2000' || body.success !== true) {
    throw new Error(`查询共享库版本失败: ${pid} ${body.message || body.msg || body.code}`);
  }
  const minors = Array.isArray(body.data) ? body.data : [];
  if (!minors.length) {
    throw new Error(`共享库无可用版本: ${pid}`);
  }
  const allRevisions = [];
  for (const minor of minors) {
    const revisions = Array.isArray(minor?.revisionList) ? minor.revisionList : [];
    for (const rev of revisions) {
      allRevisions.push(rev);
    }
  }
  if (!allRevisions.length) {
    throw new Error(`共享库无修订版本: ${pid}`);
  }
  allRevisions.sort((a, b) =>
    compareVersionDesc(a?.revisionVersionNo, b?.revisionVersionNo)
  );
  const latest = allRevisions[0];
  if (!latest?.revisionVersionId) {
    throw new Error(`共享库最新版本缺少revisionVersionId: ${pid}`);
  }
  return latest.revisionVersionId;
}

async function syncSharedLibs() {
  const sharedCfg = loadSharedLibConfig();
  if (!sharedCfg.projectVersionId || !sharedCfg.headers.authorization) {
    logger.info('共享库上传跳过: 缺少配置');
    return;
  }
  if (!sharedCfg.libs.length) {
    logger.info('共享库上传跳过: libs 为空');
    return;
  }
  const listResponse = await axios.get(
    `${sharedCfg.getListUrl}?projectVersionId=${sharedCfg.projectVersionId}`,
    { headers: sharedCfg.headers }
  );
  const listBody = listResponse.data || {};
  if (listBody.code !== '2000' || listBody.success !== true) {
    throw new Error(`查询共享库失败: ${listBody.message || listBody.msg || listBody.code}`);
  }
  const existing = Array.isArray(listBody.data) ? listBody.data : [];
  const existingMap = new Map(
    existing.map(item => [`${item.pid || ''}::${item.msAlias || ''}`, item])
  );
  let uploadCount = 0;
  for (const lib of sharedCfg.libs) {
    const key = `${lib.pid || ''}::${lib.msAlias || ''}`;
    if (existingMap.has(key)) {
      logger.info(`共享库已存在，跳过: ${lib.pid} (${lib.msAlias})`);
      continue;
    }
    if (!lib?.pid || !lib?.msAlias) {
      throw new Error('共享库配置必须包含 pid 和 msAlias');
    }
    const libProjectId = await queryLibProjectIdByPid(sharedCfg, lib.pid);
    const libVersionId = await queryLatestLibVersionId(sharedCfg, libProjectId, lib.pid);
    const payload = {
      libProjectId,
      libVersionId,
      pid: lib.pid,
      projectVersionId: sharedCfg.projectVersionId,
      msAlias: lib.msAlias
    };
    const addResponse = await axios.post(sharedCfg.addUrl, payload, {
      headers: {
        ...sharedCfg.headers,
        'content-type': 'application/json'
      }
    });
    const addBody = addResponse.data || {};
    if (addBody.code !== '2000' || addBody.success !== true) {
      throw new Error(
        `上传共享库失败: ${lib.pid} (${lib.msAlias}) ${addBody.message || addBody.msg || addBody.code}`
      );
    }
    uploadCount += 1;
    logger.success(`共享库上传成功: ${lib.pid} (${lib.msAlias})`);
  }
  logger.success(`共享库处理完成，新增数量=${uploadCount}`);
}

async function syncThirdLibs() {
  const thirdCfg = loadThirdLibConfig();
  if (!thirdCfg.projectVersionId || !thirdCfg.headers.authorization) {
    logger.info('第三方开源库上传跳过: 缺少配置');
    return;
  }
  if (!thirdCfg.libs.length) {
    logger.info('第三方开源库上传跳过: thirdLibs 为空');
    return;
  }
  const listResponse = await axios.get(
    `${thirdCfg.getListUrl}?projectVersionId=${thirdCfg.projectVersionId}`,
    { headers: thirdCfg.headers }
  );
  const listBody = listResponse.data || {};
  if (listBody.code !== '2000' || listBody.success !== true) {
    throw new Error(`查询第三方开源库失败: ${listBody.message || listBody.msg || listBody.code}`);
  }
  const existing = Array.isArray(listBody.data) ? listBody.data : [];
  const existingNameSet = new Set(
    existing
      .map(item => `${item?.libName || ''}`.trim().toLowerCase())
      .filter(Boolean)
  );
  let uploadCount = 0;
  for (const lib of thirdCfg.libs) {
    if (!lib?.libName) {
      throw new Error('thirdLibs 配置必须包含 libName');
    }
    const libName = `${lib.libName}`.trim();
    const libVersion = `${lib.libVersion || 'latest'}`.trim();
    const key = libName.toLowerCase();
    if (existingNameSet.has(key)) {
      logger.info(`第三方开源库已存在，跳过: ${libName}`);
      continue;
    }
    const payload = {
      projectVersionId: thirdCfg.projectVersionId,
      libId: '',
      libName,
      libVersion
    };
    const addResponse = await axios.post(thirdCfg.addUrl, payload, {
      headers: {
        ...thirdCfg.headers,
        'content-type': 'application/json'
      }
    });
    const addBody = addResponse.data || {};
    if (addBody.code !== '2000' || addBody.success !== true) {
      throw new Error(`上传第三方开源库失败: ${libName} ${addBody.message || addBody.msg || addBody.code}`);
    }
    uploadCount += 1;
    existingNameSet.add(key);
    logger.success(`第三方开源库上传成功: ${libName}@${libVersion}`);
  }
  logger.success(`第三方开源库处理完成，新增数量=${uploadCount}`);
}

// 获取云端文件列表
async function getCloudFileList() {
  try {
    const response = await axios.get(`${config.cloudUrl}?projectVersionId=${config.projectVersionId}`, {
      headers: config.headers,
      timeout: DEFAULT_TIMEOUT
    });
    
    if (response.data.code === '2000' && response.data.success) {
      return response.data.data.projectTree;
    } else {
      throw new Error('获取云端文件列表失败');
    }
  } catch (error) {
    logger.error(`获取云端文件列表失败: ${error.message}`);
    throw error;
  }
}

// 解析云端文件列表，筛选出Services下的代码文件
function parseCloudServiceFiles(projectTree) {
  let file={
    servicesFiles:[],
    localLibFiles:[],
    globalFiles:[]
  }
  const globalNode = projectTree.find(node => node.type === 'Global');
  if (globalNode&&globalNode.children) {
     globalNode.children.forEach(service => {
      file.globalFiles.push(service);
    });
  }
  const servicesNode = projectTree.find(node => node.type === 'Services');
  if (servicesNode&&servicesNode.children) {
     servicesNode.children.forEach(service => {
      file.servicesFiles.push(service);
    });
  }

  const localLibs = projectTree.find(node => node.type === 'LocalLibs');
  if (localLibs&&localLibs.children) {
    localLibs.children.forEach(service => {
      file.localLibFiles.push(service);
    });
  }
  return file;
}

// 读取本地目录的所有文件
function readLocalFiles(dir) {
  const files = [];
  const entries = fs.readdirSync(dir, { withFileTypes: true });
  
  entries.forEach(entry => {
    const fullPath = path.join(dir, entry.name);
    if (entry.isFile()) {
      files.push(entry.name);
    }
  });
  
  return files;
}

// 调用tryLock接口获取文件id
async function tryLockFile(fileId) {
  return withRetry(async () => {
    try {
      const response = await axios.get(`${config.tryLockUrl}?projectVersionId=${config.projectVersionId}&fileId=${fileId}`, {
        headers: config.headers,
        timeout: DEFAULT_TIMEOUT
      });
      
     // console.log(`tryLock响应:`, response.data);
      return response.data;
    } catch (error) {
      logger.error(`调用tryLock接口失败: ${error.message}`);
      throw error;
    }
  });
}

// 主函数
async function main() {
  try {
    logger.separator('开始同步本地文件到中台云端');
    
    // 验证配置
    if (!config.projectVersionId) {
      logger.error('请在package.json的uploadConfig中配置projectVersionId');
      logger.info('提示: 打开中台项目点击开发进入IDE，复制浏览器地址参数`projectVersionId`');
      return;
    }
    
    if (!config.headers.authorization) {
      logger.error('请在package.json的uploadConfig中配置authorization');
      logger.info('提示: 按F12进入开发者工具选择网络复制请求头参数`authorization`头信息');
      return;
    }

    await syncSharedLibs();
    await syncThirdLibs();
    
    logger.info(`项目ID: ${config.projectVersionId}`);
    logger.info(`本地src路径: ${config.localRoot}`);
    
    const projectTree = await getCloudFileList();
    const cloudServiceFiles = parseCloudServiceFiles(projectTree);
    
    await handInit(cloudServiceFiles);
    let localRoot=`${config.localRoot}\\services`;
    
    // 删除云端存在但本地不存在的 services
    await checkAndRemoveNonExistent(cloudServiceFiles,localRoot);
    
    // 删除云端存在但本地不存在的 local-lib
    await checkAndRemoveLocalLib(cloudServiceFiles);
    
    // 新增/修改 services
    await handSevices(cloudServiceFiles,localRoot);
    
    // 新增/修改 local-lib
    await handLocalLib(cloudServiceFiles);
   
    logger.separator('同步完成');
  } catch (error) {
    logger.error(`执行过程中发生错误: ${error.message}`);
  }
}
/**
 * 提交Init文件
 */
async function handInit(cloudServiceFiles) {
  let localRoot=`${config.localRoot}\\init`;
  const localInitFiles = readLocalFiles(localRoot);
  
  if (localInitFiles.length === 0) return;
  
  logger.info('检测 Init 文件...');
  
  for (const localFileName of localInitFiles) {
    if(localFileName!='initScript.ts'){
      continue;
    }
    
    let serviceName=localFileName.split('.')[0].toLowerCase();
    let cloudFile = cloudServiceFiles.globalFiles.find(service => service.code.toLowerCase()==serviceName);
  
    if(!cloudFile){
      logger.warn(`Init 文件 ${localFileName} 在中台不存在，跳过`);
      continue;
    }
    
    let isLocked=true;
    if(cloudFile.versionStatus&&!cloudFile.versionStatus.locked){
      isLocked=false;
      let lockResult = await tryLockFile(cloudFile.key);
      if(lockResult&&lockResult.code=='2000'&&lockResult.data){
        cloudFile.versionStatus.locked=true;
        cloudFile.versionStatus.lockId=lockResult.data.id;
        isLocked=true;
      } else {
        logger.error(`Init 文件 ${localFileName} 锁定失败`);
      }
    }
    
    if(!isLocked){
      continue;
    }
    
    let saveResult=await saveDraft(localFileName,cloudFile.versionStatus.lockId, cloudFile.key,localRoot);
    if(saveResult&&saveResult.code!='-1111'){
      if(saveResult&&saveResult.code=='2000'){
        logger.success(`Init 文件 ${localFileName} 提交成功`);
      } else {
        logger.error(`Init 文件 ${localFileName} 提交失败`);
      }
    }
    
    let unlockResult=await unlockFile(cloudFile.versionStatus.lockId);
    if(unlockResult&&unlockResult.code=='2000'){
      logger.success(`Init 文件 ${localFileName} 解锁成功`);
    } else {
      logger.error(`Init 文件 ${localFileName} 解锁失败`);
    }
  }
}
/**
 * 提交services文件（入口函数）
 */
async function handSevices(cloudServiceFiles, localRoot, fileFolderId) {
  logger.important('开始处理 Services 目录');
  await processServicesDirectory(cloudServiceFiles, localRoot, fileFolderId);
}
/**
 * 递归查找所有 FileFolder 节点
 */
function findAllFileFolders(nodes, result = []) {
  if (!nodes || !Array.isArray(nodes)) {
    return result;
  }
  for (const node of nodes) {
    if (node.type === 'FileFolder') {
      result.push(node);
    }
    if (node.children && node.children.length > 0) {
      findAllFileFolders(node.children, result);
    }
  }
  return result;
}

/**
 * 统一的递归处理 services 目录（同时处理文件和文件夹）
 */
async function processServicesDirectory(cloudServiceFiles, localDir, parentFolderId) {
  const entries = fs.readdirSync(localDir, { withFileTypes: true });
  
  // 分离文件和文件夹
  const files = entries.filter(e => e.isFile());
  const folders = entries.filter(e => e.isDirectory());
  
  // 1. 处理当前目录下的文件
  if (files.length > 0) {
    // 临时替换 servicesFiles 为当前层级的云端文件列表
    const originalServicesFiles = cloudServiceFiles.servicesFiles;
    
    // 如果有 parentFolderId，找到对应文件夹的 children
    if (parentFolderId) {
      const allCloudFolders = findAllFileFolders(originalServicesFiles);
      const currentFolder = allCloudFolders.find(f => f.key === parentFolderId);
      if (currentFolder && currentFolder.children) {
        cloudServiceFiles.servicesFiles = currentFolder.children;
      } else {
        cloudServiceFiles.servicesFiles = [];
      }
    }
    
    // 处理文件：按顺序处理，先处理主服务文件，再处理 Declare，最后处理 test
    const mainFiles = files.filter(f => !['IServiceProxy.ts','ServiceProxy.ts','WsServiceProxy.ts'].includes(f.name) && f.name.indexOf('.test.ts') === -1 && f.name.indexOf('Declare.ts') === -1);
    const declareFiles = files.filter(f => f.name.indexOf('Declare.ts') > -1);
    const testFiles = files.filter(f => f.name.indexOf('.test.ts') > -1);
    const orderedFiles = [...mainFiles, ...declareFiles, ...testFiles];
    
    for (const file of orderedFiles) {
      const localFileName = file.name;
      
      let cloudFile = null;
      let serviceName = localFileName.split('.')[0].replace('Declare', '');
      let isDeclare = localFileName.indexOf('Declare.ts') > -1;
      
      for (const service of cloudServiceFiles.servicesFiles) {
        if (service.code === serviceName) {
          if (service.children) {
            if (isDeclare) {
              cloudFile = service.children.find(child => child.type === 'ServiceDeclare');
            } else {
              if (localFileName.indexOf('.test.ts') > -1) {
                let serviceSource = service.children.find(child => child.type === 'ServiceSource');
                if (serviceSource && serviceSource.children) {
                  cloudFile = serviceSource.children.find(child => child.type === 'ServiceTest');
                }
              } else {
                cloudFile = service.children.find(child => child.type === 'ServiceSource');
              }
            }
          }
          break;
        }
      }
      
      if (!cloudFile) {
        if (localFileName.indexOf('.test.ts') === -1 && localFileName.indexOf('Declare.ts') === -1) {
          let createServicesResult = await createServices(serviceName, parentFolderId);
          if (createServicesResult && createServicesResult.code === '2000') {
            logger.success(`创建文件: ${localFileName}`);
            
            const newServiceNode = {
              "code": `${serviceName}`,
              "desc": null,
              "key": `${createServicesResult.data.serviceId || ''}`,
              "title": `${serviceName}`,
              "type": "Service",
              "path": "",
              "versionStatus": {
                "locked": false,
                "lockId": null,
                "lockCommitted": null,
                "draftRevisionId": null,
                "fileStatus": "unversioned"
              },
              "children": [
                {
                  "code": `${serviceName}`,
                  "desc": null,
                  "key": `${createServicesResult.data.declareFileId}`,
                  "title": "声明",
                  "type": "ServiceDeclare",
                  "path": `${createServicesResult.data.declareFilePath}`,
                  "versionStatus": {
                    "locked": false,
                    "lockId": null,
                    "lockCommitted": null,
                    "draftRevisionId": null,
                    "fileStatus": "unversioned"
                  },
                  "children": []
                },
                {
                  "code": `${serviceName}`,
                  "desc": null,
                  "key": `${createServicesResult.data.sourceFileId}`,
                  "title": "代码",
                  "type": "ServiceSource",
                  "path": `${createServicesResult.data.sourceFilePath}`,
                  "versionStatus": {
                    "locked": false,
                    "lockId": null,
                    "lockCommitted": null,
                    "draftRevisionId": null,
                    "fileStatus": "unversioned"
                  },
                  "children": [
                    {
                      "code": `${serviceName}`,
                      "desc": null,
                      "key": `${createServicesResult.data.testFileId}`,
                      "title": "单元测试",
                      "type": "ServiceTest",
                      "path": `${createServicesResult.data.testFilePath}`,
                      "versionStatus": {
                        "locked": false,
                        "lockId": null,
                        "lockCommitted": null,
                        "draftRevisionId": null,
                        "fileStatus": "unversioned"
                      },
                      "children": []
                    }
                  ]
                }
              ]
            };
            
            cloudServiceFiles.servicesFiles.push(newServiceNode);
            
            cloudFile = newServiceNode.children.find(c => c.type === 'ServiceSource');
          } else {
            logger.error(`创建文件失败: ${localFileName}`);
            continue;
          }
        } else {
          continue;
        }
      }
      
      let isLocked = true;
      if (cloudFile.versionStatus && !cloudFile.versionStatus.locked) {
        isLocked = false;
        let lockResult = await tryLockFile(cloudFile.key);
        if (lockResult && lockResult.code === '2000' && lockResult.data) {
          cloudFile.versionStatus.locked = true;
          cloudFile.versionStatus.lockId = lockResult.data.id;
          isLocked = true;
        } else {
          logger.error(`锁定文件失败: ${localFileName}`);
        }
      }
      
      if (!isLocked) {
        continue;
      }
      
      let saveResult = await saveDraft(localFileName, cloudFile.versionStatus.lockId, cloudFile.key, localDir);
      if (saveResult && saveResult.code !== '-1111') {
        if (saveResult && saveResult.code === '2000') {
          logger.success(`提交文件: ${localFileName}`);
        } else {
          logger.error(`提交文件失败: ${localFileName}`);
        }
      }
      
      let unlockResult = await unlockFile(cloudFile.versionStatus.lockId);
      if (unlockResult && unlockResult.code !== '2000') {
        logger.error(`解锁文件失败: ${localFileName}`);
      }
    }
    
    // 恢复原始的 servicesFiles
    cloudServiceFiles.servicesFiles = originalServicesFiles;
  }
  
  // 2. 处理当前目录下的文件夹（包括空文件夹）
  const allCloudFolders = findAllFileFolders(cloudServiceFiles.servicesFiles);
  
  for (const folder of folders) {
    const folderName = folder.name;
    const folderPath = path.join(localDir, folderName);
    
    // 查找云端对应的文件夹
    let matchingFolder = allCloudFolders.find(f => f.code === folderName);
    
    // 如果当前列表中未找到，重新获取云端文件列表
    if (!matchingFolder) {
      const newProjectTree = await getCloudFileList();
      const newCloudServiceFiles = parseCloudServiceFiles(newProjectTree);
      const allNewCloudFolders = findAllFileFolders(newCloudServiceFiles.servicesFiles);
      matchingFolder = allNewCloudFolders.find(f => f.code === folderName);
      
      if (matchingFolder) {
        cloudServiceFiles.servicesFiles = newCloudServiceFiles.servicesFiles;
      }
    }
    
    // 如果仍然未找到，尝试创建文件夹（包括空文件夹）
    if (!matchingFolder) {
      let folderResult = await createFolder(folderName, folderName, '0', parentFolderId);
      
      if (folderResult && folderResult.code === '2000' && folderResult.data) {
        logger.success(`创建目录: ${folderName}`);
        
        // 创建后重新获取云端文件列表
        const newProjectTree = await getCloudFileList();
        const newCloudServiceFiles = parseCloudServiceFiles(newProjectTree);
        const allNewCloudFolders = findAllFileFolders(newCloudServiceFiles.servicesFiles);
        matchingFolder = allNewCloudFolders.find(f => f.code === folderName);
        
        if (matchingFolder) {
          cloudServiceFiles.servicesFiles = newCloudServiceFiles.servicesFiles;
        }
      } else {
        logger.error(`创建目录失败: ${folderName}`);
        continue;
      }
    }
    
    // 递归处理子目录（即使是空文件夹也会进入，但会直接返回）
    if (matchingFolder) {
      await processServicesDirectory(cloudServiceFiles, folderPath, matchingFolder.key);
    }
  }
}
/**
 * 提交localLib文件
 * @param {*} cloudServiceFiles 
 */
async function handLocalLib(cloudServiceFiles) {
    let localRoot=`${config.localRoot}\\local-lib`;
    const localLibFiles = readLocalFiles(localRoot);
    
    if (localLibFiles.length === 0) return;
    
    logger.important('开始处理 LocalLib 目录');
    
    for (const localFileName of localLibFiles) {
      if(['IServiceProxy.ts','ServiceProxy.ts','WsServiceProxy.ts'].includes(localFileName)){
         continue;
      }
      
      let cloudFile = null;
      let serviceName=localFileName.split('.')[0];
      for (const service of cloudServiceFiles.localLibFiles) {
        if(service.code==serviceName){
          if(localFileName.indexOf('.test.ts')>-1){
            if (service.children) {
               cloudFile=service.children.find(child=>child.type=='LocalLibTest');
             }   
          }else{
            cloudFile=service;
          }
          
           break;
        }
      }
      if(!cloudFile){
        if(localFileName.indexOf('.test.ts')==-1){
          let createLocalLibResult=await createLocalLib(serviceName);
          if(createLocalLibResult&&createLocalLibResult.code=='2000'){
            logger.success(`创建LocalLib文件: ${localFileName}`);
            cloudFile={
                        "code": `${serviceName}`,
                        "desc": null,
                        "key": `${createLocalLibResult.data.sourceFileId}`,
                        "title": `${serviceName}`,
                        "type": "LocalLib",
                        "path": `${createLocalLibResult.data.sourceFilePath}`,
                        "versionStatus": {
                            "locked": false,
                            "lockId": null,
                            "lockCommitted": null,
                            "draftRevisionId": null,
                            "fileStatus": "modified"
                        },
                        "children": [
                            {
                                "code": `${serviceName}`,
                                "desc": null,
                                "key": `${createLocalLibResult.data.testFileId}`,
                                "title": "单元测试",
                                "type": "LocalLibTest",
                                "path": `${createLocalLibResult.data.testFilePath}`,
                                "versionStatus": {
                                    "locked": false,
                                    "lockId": null,
                                    "lockCommitted": null,
                                    "draftRevisionId": null,
                                    "fileStatus": "unversioned"
                                },
                                "children": [

                                ]
                            }
                        ]
                      }
          }else{
            logger.error(`创建LocalLib文件失败: ${localFileName}`);
            continue;
          }
        }else{
           continue;
        }
      }
      let isLocked=true;
      if(cloudFile.versionStatus&&!cloudFile.versionStatus.locked){
          isLocked=false;
          let lockResult=  await tryLockFile(cloudFile.key);
          if(lockResult&&lockResult.code=='2000'&&lockResult.data){
            cloudFile.versionStatus.locked=true;
            cloudFile.versionStatus.lockId=lockResult.data.id;
            isLocked=true;
          }else{
            logger.error(`锁定LocalLib文件失败: ${localFileName}`);
          }
      }
      if(!isLocked){
        continue;
      }
      let saveResult=await saveDraft(localFileName,cloudFile.versionStatus.lockId, cloudFile.key,localRoot);
      if(saveResult&&saveResult.code!='-1111'){
        if(saveResult&&saveResult.code=='2000'){
          logger.success(`提交LocalLib文件: ${localFileName}`);
        }else{
          logger.error(`提交LocalLib文件失败: ${localFileName}`);
        }
      }
      let unlockResult=await unlockFile(cloudFile.versionStatus.lockId);
      if(unlockResult&&unlockResult.code!='2000'){
        logger.error(`解锁LocalLib文件失败: ${localFileName}`);
      }
    }
}

function getUploadContent(filePath, sourcePath) {
  const fullPath = path.join(sourcePath, filePath);
  const localContent = fs.readFileSync(fullPath, 'utf8');
  if (filePath.endsWith('Declare.ts')) {
    return convertTsDeclareContentToXml(localContent);
  }
  return localContent;
}
// 文件提交函数
async function saveDraft(filePath, lockId, fileId,sourcePath) {
  return withRetry(async () => {
    try {
      // 检查文件是否修改
      const isModified = await isFileModified(filePath, fileId, lockId,sourcePath);
      
      if (!isModified) {
        return { code: '-1111', success: true, message: '文件未修改' };
      }
      
      // 读取文件内容
      const content = getUploadContent(filePath, sourcePath);
      
      // 创建FormData对象
      const formData = new FormData();
      formData.append('projectVersionId', config.projectVersionId);
      formData.append('lockId', lockId);
      formData.append('content', content);
      
      const response = await axios.post(config.saveDraftUrl, formData, {
        headers: {
          ...config.headers,
          ...formData.getHeaders()
        },
        timeout: DEFAULT_TIMEOUT
      });
      
      // 如果saveDraft成功，调用commitFile接口
      if (response.data.code === '2000' && response.data.success && response.data.data && response.data.data.revisionId) {
        await commitFile(lockId, response.data.data.revisionId);
      }
      
      return response.data;
    } catch (error) {
      logger.error(`调用saveDraft接口时发生错误: ${error.message}`);
      throw error;
    }
  });
}
//检查文件是否修改
// 获取云端文件内容
async function getCloudFileContent(fileId, lockId) {
  try {
    const getTextFileUrl = `https://me.keytop.cn/fms-webide-server/getTextFile?projectVersionId=${config.projectVersionId}&fileId=${fileId}&lockId=${lockId}`;
    const response = await axios.get(getTextFileUrl, {
      headers: config.headers,
      timeout: DEFAULT_TIMEOUT
    });
    
    //console.log(`getTextFile响应:`, response.data);
    return response.data.data?.content || '';
  } catch (error) {
    logger.error(`调用getTextFile接口失败: ${error.message}`);
    throw error;
  }
}

// 检查文件是否修改
async function isFileModified(filePath, fileId, lockId,sourcePath) {
  try {
    const localContent = getUploadContent(filePath, sourcePath);
    
    // 获取云端文件内容
    const cloudContent = await getCloudFileContent(fileId, lockId);
    
    // 比较内容
    return localContent !== cloudContent;
  } catch (error) {
    logger.error(`检查文件是否修改时发生错误: ${error.message}`);
    return true; // 出错时默认认为已修改，确保文件会被提交
  }
}

// 提交文件函数
async function commitFile(lockId, revisionId) {
  return withRetry(async () => {
    try {
      const formData = new FormData();
      formData.append('projectVersionId', config.projectVersionId);
      formData.append('lockId', lockId);
      formData.append('unlock', 'false');
      
      const response = await axios.post(config.commitFileUrl, formData, {
        headers: {
          ...config.headers,
          ...formData.getHeaders()
        },
        timeout: DEFAULT_TIMEOUT
      });
      
      return response.data;
    } catch (error) {
      logger.error(`调用commitFile接口时发生错误: ${error.message}`);
      throw error;
    }
  });
}
// 创建Services文件夹函数
async function createFolder(code,name,seqNo,fileFolderId) {
  try {
    const formData = new FormData();
    formData.append('projectVersionId', config.projectVersionId);
    formData.append('code', code);
    formData.append('name', name);
    formData.append('seqNo', seqNo??0);
    formData.append('parentId', fileFolderId?fileFolderId:'Services');
    
    const response = await axios.post(config.createFolderUrl, formData, {
      headers: {
        ...config.headers,
        ...formData.getHeaders()
      }
    });
    
    return response.data;
  } catch (error) {
    logger.error(`调用createFolder接口时发生错误: ${error.message}`);
    return null;
  }
}
// 创建Services文件函数
async function createServices(code,fileFolderId) {
  try {
    const formData = new FormData();
    formData.append('projectVersionId', config.projectVersionId);
    formData.append('code', code);
    formData.append('desc', '');
    if(fileFolderId){
      formData.append('fileFolderId', fileFolderId);
    }
    
    const response = await axios.post(config.createServicesUrl, formData, {
      headers: {
        ...config.headers,
        ...formData.getHeaders()
      }
    });
    
    return response.data;
  } catch (error) {
    logger.error(`调用createServices接口时发生错误: ${error.message}`);
    return null;
  }
}
// 创建localLib文件函数
async function createLocalLib(code) {
  try {
    const formData = new FormData();
    formData.append('projectVersionId', config.projectVersionId);
    formData.append('code', code);
    
    const response = await axios.post(config.createLocalLibUrl, formData, {
      headers: {
        ...config.headers,
        ...formData.getHeaders()
      }
    });
    
    return response.data;
  } catch (error) {
    logger.error(`调用createLocalLib接口时发生错误: ${error.message}`);
    return null;
  }
}
//删除文件
// 删除locallib接口
async function removeLocallib(code) {
  try {
    const formData = new FormData();
    formData.append('projectVersionId', config.projectVersionId);
    formData.append('code', code);
    
    const response = await axios.post(config.removeLocalLib, formData, {
      headers: {
        ...config.headers,
        ...formData.getHeaders()
      }
    });
    
    return response.data;
  } catch (error) {
    logger.error(`调用removeLocallib接口时发生错误: ${error.message}`);
    return null;
  }
}
// 删除服务接口
async function removeService(code) {
  try {
    const formData = new FormData();
    formData.append('projectVersionId', config.projectVersionId);
    formData.append('code', code);
    
    const response = await axios.post(config.removeServices, formData, {
      headers: {
        ...config.headers,
        ...formData.getHeaders()
      }
    });
    
    return response.data;
  } catch (error) {
    logger.error(`调用removeService接口时发生错误: ${error.message}`);
    return null;
  }
}

// 删除文件夹接口
async function removeFileFolder(id) {
  try {
    const formData = new FormData();
    formData.append('projectVersionId', config.projectVersionId);
    formData.append('id', id);
    
    const response = await axios.post(config.removeServicesFolder, formData, {
      headers: {
        ...config.headers,
        ...formData.getHeaders()
      }
    });
    return response.data;
  } catch (error) {
    logger.error(`调用removeFileFolder接口时发生错误: ${error.message}`);
    return null;
  }
}

// 检查并删除不存在的文件和目录
async function checkAndRemoveNonExistent(cloudServiceFiles,localRoot) {
  logger.info('检查并删除云端存在但本地不存在的 Services...');
  await checkAndRemoveRecursive(cloudServiceFiles.servicesFiles,localRoot);
}

// 递归检查并删除不存在的文件和目录
async function checkAndRemoveRecursive(items, currentPath) {
  for (let i = items.length - 1; i >= 0; i--) {
    const item = items[i];
    const itemPath = path.join(currentPath, item.code);
    
    if (item.type === 'FileFolder') {
      // 检查目录是否存在
      if (!fs.existsSync(itemPath) || !fs.lstatSync(itemPath).isDirectory()) {
        logger.warn(`目录 ${item.code} 本地不存在，正在删除云端目录`);
        // 递归检查子目录和文件
        if (item.children && item.children.length > 0) {
          await checkAndRemoveRecursive(item.children, itemPath);
        }
        // 删除文件夹
        const result = await removeFileFolder(item.key);
        if (result && result.code === '2000') {
          logger.success(`已删除云端目录: ${item.code}`);
        } else {
          logger.error(`删除云端目录失败: ${item.code}`);
        }
      } else {
        // 目录存在，递归检查子目录
        if (item.children && item.children.length > 0) {
          await checkAndRemoveRecursive(item.children, itemPath);
        }
      }
    } else if (item.type === 'Service') {
      // 检查服务文件是否存在
      const serviceFilePath = path.join(currentPath, `${item.code}.ts`);
      if (!fs.existsSync(serviceFilePath)) {
        logger.warn(`服务文件 ${item.code}.ts 本地不存在，正在删除云端服务`);
        // 删除服务
        const result = await removeService(item.code);
        if (result && result.code === '2000') {
          logger.success(`已删除云端服务: ${item.code}`);
        } else {
          logger.error(`删除云端服务失败: ${item.code}`);
        }
      }
    }
  }
}

// 删除lib文件
async function checkAndRemoveLocalLib(cloudServiceFiles) {
  let currentPath=`${config.localRoot}\\local-lib`;
  let items=cloudServiceFiles.localLibFiles;
  
  logger.info('检查并删除云端存在但本地不存在的 LocalLib...');
  
  for (let i = items.length - 1; i >= 0; i--) {
    const item = items[i];
    if (item.type === 'LocalLib') {
      // 检查服务文件是否存在
      const serviceFilePath = path.join(currentPath, `${item.code}.ts`);
      if (!fs.existsSync(serviceFilePath)) {
        logger.warn(`LocalLib文件 ${item.code}.ts 本地不存在，正在删除云端文件`);
        // 删除服务
        const result = await removeLocallib(item.code);
        if (result && result.code === '2000') {
          logger.success(`已删除云端LocalLib: ${item.code}`);
        } else {
          logger.error(`删除云端LocalLib失败: ${item.code}`);
        }
      }
    }
  }
}

// 文件解锁函数
async function unlockFile(lockId) {
  return withRetry(async () => {
    try {
      const unlockUrl = `https://me.keytop.cn/fms-webide-server/unlock?lockId=${lockId}`;
      const response = await axios.get(unlockUrl, {
        headers: config.headers,
        timeout: DEFAULT_TIMEOUT
      });
      
      return response.data;
    } catch (error) {
      logger.error(`调用unlock接口失败: ${error.message}`);
      throw error;
    }
  });
}


// 执行主函数
main();
