/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { appTasks } from '@ohos/hvigor-ohos-plugin';
import {
  BaseAnalyzeResult,
  ExtensionContext,
  Logger,
  PluginExtension,
  registerPluginExtension
} from '@hadss/hmrouter-plugin';
import { ClassDeclaration, Expression, PropertyAssignment, SourceFile, SyntaxKind } from 'ts-morph';

interface RouterInfo {
  name: string;
  pageSourceFile: string;
  buildFunction: string;
  customData: Record<string, any>;
}

interface MyExtensionContext extends ExtensionContext {
  customPages?: RouterInfo[];
  routerMap: RouterInfo[];
}

interface MyAnalyzeResult extends BaseAnalyzeResult {
  [key: string]: any;
}

// 示例1: RouterParam注解分析器
export class RouterParamAnalyzer {
  readonly name = 'RouterParamAnalyzer';

  analyze(sourceFile: SourceFile, filePath: string, context: MyExtensionContext): void {
    Logger.debug('', `开始分析RouterParam注解: ${filePath}`);

    // 获取所有ExpressionStatement以获取struct关键字后面的组件名称
    const viewNameArr = sourceFile
      .getChildrenOfKind(SyntaxKind.ExpressionStatement)
      .map((node) => node.getText())
      .filter((text) => text !== 'struct');

    // 解析结构体声明中的RouterParam注解
    sourceFile.getChildrenOfKind(SyntaxKind.MissingDeclaration).forEach((node, index) => {
      node.getChildrenOfKind(SyntaxKind.Decorator).forEach((decorator) => {
        this.getDecorator(decorator, viewNameArr, index, filePath, context);
      });
    });
  }

  private getDecorator(decorator: any, viewNameArr: any, index: number, filePath: any, context: MyExtensionContext): void {
    if (decorator.getName() === 'RouterParam') {
      // 解析RouterParam注解的参数
      const result: MyAnalyzeResult = {
        name: viewNameArr[index],
        annotation: decorator.getName(),
        sourceFilePath: filePath
      };

      // 解析装饰器参数
      decorator.getArguments().forEach((arg) => {
        const objLiteral = arg.asKind(SyntaxKind.ObjectLiteralExpression);
        if (objLiteral) {
          this.handleObjLiteral(objLiteral, result);
        }
      });

      // 为组件添加模板数据，用于代码生成
      context.addTemplateData(result.name, {
        paramType: result.paramType || 'default',
        isCustomParam: true,
        customParams: result.params || [],
        sourceFile: filePath
      });

      Logger.debug('', `发现RouterParam注解: ${result.name}`);
    }
  }

  private handleObjLiteral(objLiteral: any, result: MyAnalyzeResult): void {
    objLiteral.getProperties().forEach((prop) => {
      if (prop.getKind() === SyntaxKind.PropertyAssignment) {
        const propertyAssignment = prop as PropertyAssignment;
        const propertyName = propertyAssignment.getName();
        const initializer = propertyAssignment.getInitializer();

        if (initializer) {
          // 将解析结果添加到result对象
          result[propertyName] = this.parsePrimitiveValue(initializer);
        }
      }
    });
  }

  private parsePrimitiveValue(value: Expression): string {
    let propertyValue;
    switch (value.getKind()) {
      case SyntaxKind.StringLiteral:
        propertyValue = value.asKind(SyntaxKind.StringLiteral)?.getLiteralValue();
        break;
      case SyntaxKind.NumericLiteral:
        propertyValue = value.asKind(SyntaxKind.NumericLiteral)?.getLiteralValue();
        break;
      case SyntaxKind.TrueKeyword:
        propertyValue = true;
        break;
      case SyntaxKind.FalseKeyword:
        propertyValue = false;
        break;
      case SyntaxKind.ArrayLiteralExpression:
        propertyValue = value
          .asKind(SyntaxKind.ArrayLiteralExpression)
          ?.getElements()
          .map((item) => {
            if (item.getKind() === SyntaxKind.StringLiteral) {
              return item.asKind(SyntaxKind.StringLiteral)?.getLiteralValue();
            }
            return null;
          })
          .filter(item => item !== null);
        break;
    }
    return propertyValue;
  }
}

// 示例2: CustomPage注解分析器
export class CustomPageAnalyzer {
  readonly name = 'CustomPageAnalyzer';

  analyze(sourceFile: SourceFile, filePath: string, context: MyExtensionContext): void {
    Logger.debug('', `开始分析CustomPage注解: ${filePath}`);

    // 分析使用@CustomPage注解的类
    sourceFile.getClasses().forEach((cls: ClassDeclaration) => {
      cls.getDecorators().forEach(decorator => {
        this.getDecorator(decorator, cls, filePath, context);
      });
    });
  }

  private getDecorator(decorator: any, cls: ClassDeclaration, filePath: any, context: MyExtensionContext): void {
    if (decorator.getName() === 'CustomPage') {
      const className = cls.getName() || '';

      // 创建分析结果
      const result: MyAnalyzeResult = {
        name: className,
        annotation: 'CustomPage',
        sourceFilePath: filePath
      };

      // 解析装饰器参数
      decorator.getArguments().forEach((arg) => {
        const objLiteral = arg.asKind(SyntaxKind.ObjectLiteralExpression);
        if (objLiteral) {
          this.handleObjLiteral(objLiteral, result);
        }
      });

      // 添加分析结果
      context.addAnalyzeResults(result);

      // 存储自定义页面路径信息
      const customPages = context.customPages || [];
      customPages.push(result);
      context.customPages = customPages;

      Logger.debug('', `发现CustomPage注解: ${className}, pageUrl: ${result.pageUrl}`);
    }
  }

  private handleObjLiteral(objLiteral: any, result: MyAnalyzeResult): void {
    objLiteral.getProperties().forEach((prop) => {
      if (prop.getKind() === SyntaxKind.PropertyAssignment) {
        const propertyAssignment = prop as PropertyAssignment;
        const propertyName = propertyAssignment.getName();
        const initializer = propertyAssignment.getInitializer();

        if (initializer && initializer.getKind() === SyntaxKind.StringLiteral) {
          result[propertyName] = initializer.asKind(SyntaxKind.StringLiteral)?.getLiteralValue();
        }
      }
    });
  }
}

// 插件扩展类
export class CustomPluginExtension extends PluginExtension<MyExtensionContext> {
  get name(): string {
    return 'CustomPluginExtension';
  }

  // 提供注解分析器
  afterAnnotationAnalysis(sourceFile: SourceFile, filePath: string, context: MyExtensionContext): void {
    const analyzers = [new RouterParamAnalyzer(), new CustomPageAnalyzer()];
    for (const analyzer of analyzers) {
      analyzer.analyze(sourceFile, filePath, context);
    }
  }

  // 代码生成阶段，可以使用RouterParam注解分析结果
  afterCodeGeneration(context: MyExtensionContext): void {
    // 获取所有模板数据
    const templateDataMap = context.getTemplateDataMap();

    // 示例: 输出找到的RouterParam数据
    for (const [componentName, templateData] of templateDataMap.entries()) {
      if (templateData.isCustomParam) {
        Logger.info(
          this.name,
          `组件 ${componentName} 将使用自定义参数类型: ${templateData.paramType}`
        );
        // 实际场景可以在此生成额外的代码
      }
    }
  }

  // 路由表构建阶段，将CustomPage注解分析结果添加到路由表
  afterRouterMapBuilding(context: MyExtensionContext): void {
    // 从私有存储获取CustomPage分析结果
    const customPages = context.customPages || [];

    // 将CustomPage添加到路由表
    for (const page of customPages) {
      const pageUrl = page.customData.pageUrl;
      if (pageUrl) {
        // 检查路由表中是否已存在该路径
        const existingRoute = context.routerMap.find(route => route.customData.pageUrl === pageUrl);
        if (!existingRoute) {
          // 创建新的路由项并添加到路由表
          context.routerMap.push({
            name: pageUrl,
            buildFunction: page.name,
            pageSourceFile: page.pageSourceFile,
            customData: {
              ...page.customData,
            }
          });

          Logger.info(
            this.name,
            `添加自定义页面到路由表: ${pageUrl} -> ${page.name}`
          );
        }
      }
    }
  }
}

// 注册扩展
registerPluginExtension(new CustomPluginExtension());

export default {
  system: appTasks,
  plugins: []
};
