using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MiGu.Server.Configs;
using MiGu.Server.Launcher;

namespace MiGu.Server.Controllers;

/// <summary>
/// 配置向导 API。登录后若 <c>deployment.Configured=false</c>（见 <c>LoginResponse.NeedsWizard</c>），
/// 前端进入向导：
/// <list type="bullet">
///   <item><c>GET  /api/wizard/options</c>：可选项目录（导航方式 / 模块 / 业务场景模板）。</item>
///   <item><c>GET  /api/wizard/profile</c>：回显当前部署画像（含由导航选型推导的激活场景 id）。</item>
///   <item><c>PUT  /api/wizard/profile</c>：保存并置 <c>Configured=true</c>（仅 Platform scope）。</item>
///   <item><c>POST /api/wizard/reset</c>：把 <c>Configured</c> 置回 false 以重新引导（仅 Platform scope）。</item>
/// </list>
/// 说明：保存时即把选型固化为单一事实来源 <c>deployment</c> section，并同步联动 Launcher ——
/// <see cref="SaveProfile"/> 调 <c>WriteActiveScenes</c> 写 <c>plugins/active-scenes.json</c> / 透传 <c>--scenes</c>，
/// 驱动 SimpleLite 下次启动选择性加载选定的导航场景插件。
/// </summary>
[ApiController]
[Authorize]
[Route("api/wizard")]
public class WizardController : ControllerBase
{
    private readonly ConfigStore _store;
    private readonly SimpleLiteLauncher _launcher;
    private readonly ILogger<WizardController> _log;

    public WizardController(ConfigStore store, SimpleLiteLauncher launcher, ILogger<WizardController> log)
    {
        _store = store;
        _launcher = launcher;
        _log = log;
    }

    [HttpGet("options")]
    public IActionResult Options()
    {
        return Ok(new
        {
            navigationKinds = DeploymentCatalog.NavigationKinds,
            modules = DeploymentCatalog.Modules,
            scenarios = _store.Get("scenario").Payload
        });
    }

    [HttpGet("profile")]
    public IActionResult GetProfile() => Ok(Project(_store.GetDeployment()));

    /// <summary>当前部署画像对菜单的裁剪结果（供前端做面板/能力级裁剪与排查）。</summary>
    [HttpGet("effective-pages")]
    public IActionResult EffectivePages()
    {
        var dp = _store.GetDeployment();
        return Ok(new
        {
            configured = dp.Configured,
            tailorablePages = DeploymentCatalog.TailorablePages(),
            enabledPages = DeploymentCatalog.EnabledPages(dp),
            hiddenPages = DeploymentCatalog.HiddenPages(dp)
        });
    }

    [HttpPut("profile")]
    [Authorize(Policy = "PlatformScope")]
    public IActionResult SaveProfile([FromBody] SaveWizardRequest req)
    {
        if (req == null)
            return BadRequest(new { message = "请求体不能为空" });

        var user = User.Identity?.Name ?? User.FindFirstValue(ClaimTypes.NameIdentifier) ?? "";
        var profile = new DeploymentProfile(
            Configured: true,
            PlatformType: string.IsNullOrWhiteSpace(req.PlatformType) ? "standard" : req.PlatformType.Trim(),
            Modules: Clean(req.Modules),
            NavigationKinds: Clean(req.NavigationKinds),
            Scenarios: Clean(req.Scenarios),
            UpdatedBy: user);

        _store.PutDeployment(profile);

        // 平台 → 内核联动：把导航选型写入 SimpleLite 的 plugins/active-scenes.json（下次启动选择性加载；
        // 已运行实例可由前端再调 POST /api/sl/projection/scenes/apply 触发增量 reload）。
        // scene.device（门/充电桩/按钮盒驱动）为各类项目通用能力，向导暂无独立选项，固定并入激活集合；
        // scene.vda5050 等协议插件保持按需（不在集合则不加载）。基座 StandardScene.dll 由内核按
        // 清单 requiresCore 自动 alwaysLoad，无需在此声明。
        var sceneIds = profile.ToActiveSceneIds().Concat(new[] { "scene.device" }).Distinct().ToList();
        var write = _launcher.WriteActiveScenes(sceneIds, alwaysLoad: null, source: "deployment-profile");

        _log.LogInformation("部署向导已保存 by={User} nav=[{Nav}] scenes=[{Scenes}] activeScenesWritten={Ok}",
            user, string.Join(",", profile.NavigationKinds), string.Join(",", sceneIds), write.Ok);

        return Ok(Project(profile, write));
    }

    [HttpPost("reset")]
    [Authorize(Policy = "PlatformScope")]
    public IActionResult Reset()
    {
        var reset = _store.GetDeployment() with { Configured = false };
        _store.PutDeployment(reset);
        return Ok(Project(reset));
    }

    /// <summary>
    /// 统一对外投影：camelCase 字段 + 推导出的 activeSceneIds（导航选型 → 内核场景 id）+
    /// hiddenPages（被裁剪的菜单页）+ 可选的 activeScenesWrite（保存时写 active-scenes.json 的结果）。
    /// </summary>
    private static object Project(DeploymentProfile dp, SimpleLiteLauncher.ActiveScenesWriteResult? write = null) => new
    {
        configured = dp.Configured,
        platformType = dp.PlatformType,
        modules = dp.Modules,
        navigationKinds = dp.NavigationKinds,
        scenarios = dp.Scenarios,
        updatedBy = dp.UpdatedBy,
        activeSceneIds = dp.ToActiveSceneIds(),
        hiddenPages = DeploymentCatalog.HiddenPages(dp),
        activeScenesWrite = write == null ? null : new
        {
            ok = write.Value.Ok,
            path = write.Value.Path,
            error = write.Value.Error
        }
    };

    /// <summary>去空白、去重（大小写不敏感）、保持顺序。</summary>
    private static List<string> Clean(List<string>? items)
    {
        var result = new List<string>();
        if (items == null) return result;
        foreach (var s in items)
        {
            var t = s?.Trim();
            if (!string.IsNullOrEmpty(t) && !result.Contains(t, StringComparer.OrdinalIgnoreCase))
                result.Add(t!);
        }
        return result;
    }

    public record SaveWizardRequest(
        string? PlatformType,
        List<string>? Modules,
        List<string>? NavigationKinds,
        List<string>? Scenarios);
}
