const Path = require('path');
const Fs = require('fs');

// --- helpers (module scope, do NOT rely on `this`) ---

function capitalize(str) {
  return str.charAt(0).toUpperCase() + str.slice(1);
}

function getRelativePath(absolutePath) {
  return Path.relative(Editor.Project.path, absolutePath).replace(/\\/g, '/');
}

// CC 3.x：通过 asset-db 消息刷新资源。Editor.AssetDB 是 2.x 的旧 API，已移除。
// 传入绝对路径，内部转成 db:// url 后请求刷新。
async function refreshAsset(absolutePath) {
  const relativePath = Path.relative(Editor.Project.path, absolutePath);
  const url = 'db://' + relativePath.replace(/\\/g, '/');
  try {
    await Editor.Message.request('asset-db', 'refresh-asset', url);
    console.log(`[LayerGenerator] 已刷新: ${url}`);
  } catch (err) {
    console.error(`[LayerGenerator] 刷新失败 ${url}:`, err);
  }
}

function findBundlePath(dirPath, bundleName) {
  if (!Fs.existsSync(dirPath)) return null;
  const items = Fs.readdirSync(dirPath);
  for (const item of items) {
    const fullPath = Path.join(dirPath, item);
    const stats = Fs.statSync(fullPath);

    if (stats.isDirectory()) {
      if (Path.basename(fullPath) === bundleName) {
        const metaPath = `${fullPath}.meta`;
        if (Fs.existsSync(metaPath)) {
          try {
            const metaContent = Fs.readFileSync(metaPath, 'utf8');
            if (metaContent.includes('"isBundle": true')) {
              return fullPath;
            }
          } catch (err) {
            continue;
          }
        }
      }
      const foundPath = findBundlePath(fullPath, bundleName);
      if (foundPath) return foundPath;
    }
  }
  return null;
}

function generateLayerTemplate(className) {
  return `import { _decorator, Node } from "cc";

const { ccclass } = _decorator;

@ccclass('${className}')
export class ${className} extends Framework.Layer {
    public onLoad(): void {
        super.onLoad?.();
    }

    public onEnable(): void {
        super.onEnable?.();
    }

    public onDisable(): void {
        super.onDisable?.();
    }

    public onDestroy(): void {
        super.onDestroy?.();
    }

    public start(): void {
        super.start?.();
    }

    public update(dt: number): void {
        super.update?.(dt);
    }
}
`;
}

function generateControllerTemplate(controllerClassName, layerClassName, dataClassName, layerImportPath, dataImportPath, bundleName, prefabPath) {
  return `import { ${layerClassName} } from "${layerImportPath}";
import { ${dataClassName} } from "${dataImportPath}";

export class ${controllerClassName} extends Framework.LayerController<${layerClassName}, ${dataClassName}> {
    layerDataConstructor = ${dataClassName};
    layerConstructor = ${layerClassName};

    public get layerAssetProperty(): Framework.AssetProperty {
        return {
            bundle: "${bundleName}",
            path: "${prefabPath}Layer",
        };
    }

    onInit(data?: any) {
    }
}
`;
}

function generateDataTemplate(className) {
  return `export class ${className} extends Framework.LayerData {
 
}
`;
}

// --- CC extension exports ---

module.exports = {
  load() { },
  unload() { },

  methods: {
    openPanel() {
      Editor.Panel.open('layer-generator.panel');
    },

    async generateLayer(params) {
      try {
        const { bundleName, featureName, subDir } = params;
        const className = `${capitalize(featureName)}`;
        const layerClassName = `${className}Layer`;
        const controllerClassName = `${className}Controller`;
        const dataClassName = `${className}Data`;

        const projectPath = Editor.Project.path;
        const assetsPath = Path.join(projectPath, 'assets');

        const bundlePath = findBundlePath(assetsPath, bundleName);
        if (!bundlePath) {
          Editor.Dialog.warn(`找不到 Bundle "${bundleName}" 或未配置为 Bundle！`, {
            buttons: ['确定'],
            default: 0,
          });
          return;
        }

        // 新布局: src/<subDir>/{ctr,layer,data}/...
        // - subDir 支持多级路径 (如 "popup/bank"), 先建子目录再建 ctr/layer/data
        // - 不传 subDir 时回退到 src/{ctr,layer,data} 的旧布局
        const srcBase = Path.join(bundlePath, 'src');
        const featureBase = subDir ? Path.join(srcBase, subDir) : srcBase;
        if (!Fs.existsSync(featureBase)) {
          Fs.mkdirSync(featureBase, { recursive: true });
        }

        const layerDir = Path.join(featureBase, 'layer');
        const controllerDir = Path.join(featureBase, 'ctr');
        const dataDir = Path.join(featureBase, 'data');

        [layerDir, controllerDir, dataDir].forEach((dir) => {
          if (!Fs.existsSync(dir)) {
            Fs.mkdirSync(dir, { recursive: true });
          }
        });

        // 用 Path.relative 从 controllerDir 计算到目标文件（不带 .ts 后缀）的相对路径，
        // 保证无论 subDir 有多少层都得到正确的 ../ 前缀；Windows 反斜杠转成 /。
        function toImportPath(fromDir, toFile) {
          let rel = Path.relative(fromDir, toFile).replace(/\\/g, '/');
          if (!rel.startsWith('.')) rel = './' + rel;
          return rel;
        }
        const layerImportPath = toImportPath(controllerDir, Path.join(layerDir, layerClassName));
        const dataImportPath = toImportPath(controllerDir, Path.join(dataDir, dataClassName));
        const prefabPath = subDir ? `res/prefab/${subDir}/${featureName}` : `res/prefab/${featureName}`;

        // Layer 文件
        const layerContent = generateLayerTemplate(layerClassName);
        const layerPath = Path.join(layerDir, `${layerClassName}.ts`);
        Fs.writeFileSync(layerPath, layerContent, 'utf8');

        // Controller 文件
        const controllerContent = generateControllerTemplate(
          controllerClassName,
          layerClassName,
          dataClassName,
          layerImportPath,
          dataImportPath,
          bundleName,
          prefabPath
        );
        const controllerPath = Path.join(controllerDir, `${controllerClassName}.ts`);
        Fs.writeFileSync(controllerPath, controllerContent, 'utf8');

        // LayerData 文件
        const dataContent = generateDataTemplate(dataClassName);
        const dataPath = Path.join(dataDir, `${dataClassName}.ts`);
        Fs.writeFileSync(dataPath, dataContent, 'utf8');

        // 逐个刷新生成的 ts 文件，让资源管理器立即看到新文件（而不是等下次扫描）
        await refreshAsset(layerPath);
        await refreshAsset(controllerPath);
        await refreshAsset(dataPath);

        Editor.Dialog.info(
          `生成成功！\n\n` +
          `Layer: ${getRelativePath(layerPath)}\n` +
          `Controller: ${getRelativePath(controllerPath)}\n` +
          `Data: ${getRelativePath(dataPath)}`,
          { buttons: ['确定'], default: 0 }
        );

        console.log(`[LayerGenerator] 生成成功: ${className}`);
        console.log(`  Layer: ${getRelativePath(layerPath)}`);
        console.log(`  Controller: ${getRelativePath(controllerPath)}`);
        console.log(`  Data: ${getRelativePath(dataPath)}`);

      } catch (err) {
        Editor.Dialog.error(`生成Layer失败: ${err.message}`, {
          buttons: ['确定'],
          default: 0,
        });
        console.error('[LayerGenerator] 生成失败:', err);
      }
    },
  },
};
