using Flyshot.Core.Config;
using Flyshot.Core.Domain;

namespace Flyshot.ControllerClientCompat;

/// <summary>
/// 根据旧版 ControllerClient 的机器人名称，解析当前 replacement 仓库支持的真实模型文件。
/// </summary>
public sealed class ControllerClientCompatRobotCatalog
{
    /// <summary>
    /// 保存当前现场支持的机器人名称到模型相对路径映射。
    /// </summary>
    private static readonly IReadOnlyDictionary<string, string> SupportedRobotModelMap = new Dictionary<string, string>(StringComparer.Ordinal)
    {
        ["FANUC_LR_Mate_200iD"] = Path.Combine("FlyingShot", "FlyingShot", "Models", "LR_Mate_200iD_7L.robot"),
        ["FANUC_LR_Mate_200iD_7L"] = Path.Combine("FlyingShot", "FlyingShot", "Models", "LR_Mate_200iD_7L.robot")
    };

    private readonly ControllerClientCompatOptions _options;
    private readonly RobotModelLoader _robotModelLoader;

    /// <summary>
    /// 初始化机器人兼容目录解析器。
    /// </summary>
    /// <param name="options">兼容层基础配置。</param>
    /// <param name="robotModelLoader">.robot 文件加载器。</param>
    public ControllerClientCompatRobotCatalog(
        ControllerClientCompatOptions options,
        RobotModelLoader robotModelLoader)
    {
        _options = options ?? throw new ArgumentNullException(nameof(options));
        _robotModelLoader = robotModelLoader ?? throw new ArgumentNullException(nameof(robotModelLoader));
    }

    /// <summary>
    /// 根据旧客户端的机器人名称加载对应模型。
    /// </summary>
    /// <param name="robotName">旧客户端传入的机器人名称。</param>
    /// <param name="accLimitScale">RobotConfig.json 中的加速度倍率。</param>
    /// <param name="jerkLimitScale">RobotConfig.json 中的 jerk 倍率。</param>
    /// <returns>兼容层加载出的机器人模型。</returns>
    public RobotProfile LoadProfile(string robotName, double accLimitScale = 1.0, double jerkLimitScale = 1.0)
    {
        if (string.IsNullOrWhiteSpace(robotName))
        {
            throw new ArgumentException("机器人名称不能为空。", nameof(robotName));
        }

        if (!SupportedRobotModelMap.TryGetValue(robotName, out var modelRelativePath))
        {
            throw new InvalidOperationException($"Unsupported robot name: {robotName}");
        }

        var workspaceRoot = ResolveWorkspaceRoot();
        var modelPath = Path.Combine(workspaceRoot, modelRelativePath);
        return _robotModelLoader.LoadProfile(modelPath, accLimitScale, jerkLimitScale);
    }

    /// <summary>
    /// 解析父工作区根目录，优先使用显式配置。
    /// </summary>
    /// <returns>包含 `FlyingShot/` 与 `Rvbust/` 的父工作区根目录。</returns>
    private string ResolveWorkspaceRoot()
    {
        if (!string.IsNullOrWhiteSpace(_options.WorkspaceRoot))
        {
            return Path.GetFullPath(_options.WorkspaceRoot);
        }

        var current = new DirectoryInfo(AppContext.BaseDirectory);
        while (current is not null)
        {
            // 宿主和测试都从 replacement 仓库内启动；找到 sln 后回退一级就是父工作区根目录。
            if (File.Exists(Path.Combine(current.FullName, "FlyshotReplacement.sln")))
            {
                return Path.GetFullPath(Path.Combine(current.FullName, ".."));
            }

            current = current.Parent;
        }

        throw new DirectoryNotFoundException("Unable to locate the flyshot workspace root.");
    }
}
