/*
 * Copyright (c) 2025 SimcuTeam. All rights reserved.
 * 遵循 MIT 许可证。
 * Helpers/SimApiControllerScanner：自动发现调用者包中的 MVC 控制器。
 *
 * 控制器发现机制：
 * - 通过 StackTrace 获取调用程序集，再 Assembly.GetTypes() 扫描所有类型
 * - 仓颉版通过 Error.getStackTrace() 获取调用者包名，再 PackageInfo 枚举类型，
 *   过滤出继承 Controller 的类型（含子包）
 */

package simcu::simapi.helpers

import std.collection.*
import std.core.*
import std.reflect.*
import soulsoft_web_mvc.core.*
import simcu::simapi.interfaces.*

/**
 * 控制器自动扫描器：从调用栈定位调用者包，枚举该包（含子包）中继承 Controller 的类型。
 */
public class SimApiControllerScanner {
    private init() {}

    /**
     * 扫描调用者包及其所有子包中的控制器类型。
     * @return 找到的控制器类型列表（不含抽象类型与 Controller 基类本身）。
     */
    public static func scan(): Array<TypeInfo> {
        let callerPackage = getCallerPackage()
        var result = ArrayList<TypeInfo>()
        collectControllers(callerPackage, result)
        result.toArray()
    }

    /**
     * 扫描调用者包及其所有子包中 SimApiAuthChecker 的实现类。
     * @return 找到的 checker 实现类型列表（不含抽象类型与接口本身）。
     */
    public static func scanAuthCheckers(): Array<TypeInfo> {
        let callerPackage = getCallerPackage()
        var result = ArrayList<TypeInfo>()
        collectImplementations(callerPackage, TypeInfo.of<SimApiAuthChecker>(), result)
        result.toArray()
    }

    /**
     * 获取调用者（应用）包名：遍历栈帧，跳过 simapi/soulsoft/std 等框架包，
     * 返回第一个应用包的 declaringClass。
     */
    public static func getCallerPackage(): String {
        try {
            throw Exception("probe")
        } catch (ex: Exception) {
            let st = ex.getStackTrace()
            for (el in st) {
                let name = el.declaringClass
                // 跳过本类及框架包（兼容旧包名 simapi 与新包名 simcu::simapi）
                if (name.isEmpty()) {
                    continue
                }
                if (name.startsWith("simapi.") || name == "simapi") {
                    continue
                }
                if (name.startsWith("simcu::simapi.") || name == "simcu::simapi") {
                    continue
                }
                if (name.startsWith("soulsoft_") || name.startsWith("std.") || name.startsWith("stdx.")) {
                    continue
                }
                return name
            }
            return ""
        }
    }

    /**
     * 收集指定包及其子包中的控制器类型。
     */
    private static func collectControllers(packageName: String, result: ArrayList<TypeInfo>): Unit {
        if (packageName.isEmpty()) {
            return
        }
        try {
            let info = PackageInfo.get(packageName)
            for (ti in info.typeInfos) {
                if (isController(ti)) {
                    result.add(ti)
                }
            }
            // 递归扫描子包（subPackages 的 name 是短名，需拼接全限定名）
            for (sub in info.subPackages) {
                collectControllers("${packageName}.${sub.name}", result)
            }
        } catch (_: Exception) {
            // 包不存在时跳过
        }
    }

    /**
     * 判断类型是否为控制器：
     * - 继承 Controller（soulsoft_web_mvc.core.Controller）
     * - 非抽象类
     * - 不是 Controller 基类本身
     */
    private static func isController(typeInfo: TypeInfo): Bool {
        if (let classTypeInfo: ClassTypeInfo <- typeInfo) {
            if (classTypeInfo.isAbstract()) {
                return false
            }
            if (typeInfo == TypeInfo.of<Controller>()) {
                return false
            }
            return typeInfo.isSubtypeOf(TypeInfo.of<Controller>())
        }
        false
    }

    /// 收集指定包及其子包中实现指定接口的非抽象类
    private static func collectImplementations(packageName: String, interfaceType: TypeInfo,
        result: ArrayList<TypeInfo>): Unit {
        if (packageName.isEmpty()) {
            return
        }
        try {
            let info = PackageInfo.get(packageName)
            for (ti in info.typeInfos) {
                if (isImplementation(ti, interfaceType)) {
                    result.add(ti)
                }
            }
            for (sub in info.subPackages) {
                collectImplementations("${packageName}.${sub.name}", interfaceType, result)
            }
        } catch (_: Exception) {
            // 包不存在时跳过
        }
    }

    /// 判断类型是否为接口的非抽象实现类
    private static func isImplementation(typeInfo: TypeInfo, interfaceType: TypeInfo): Bool {
        if (let classTypeInfo: ClassTypeInfo <- typeInfo) {
            if (classTypeInfo.isAbstract()) {
                return false
            }
            if (typeInfo == interfaceType) {
                return false
            }
            return typeInfo.isSubtypeOf(interfaceType)
        }
        false
    }
}
