using System.Text.Json;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using MiGu.Server.Auth;
using MiGu.Server.Launcher;

namespace MiGu.Server.Controllers;

/// <summary>
/// 读取 SimpleLite 地图固定目录下的 JSON 原文，供平台「地图管理」右侧预览。
/// 先向 SimpleLite 拉取 maps 列表拿到 directory，再读本机同路径文件（与 SimpleLite 同机部署）。
/// </summary>
[ApiController]
[Authorize]
[Route("api/maps")]
public class MapsContentController : ControllerBase
{
    private readonly IHttpClientFactory _httpFactory;
    private readonly InternalTokenStore _internalToken;
    private readonly SimpleLiteOptions _sl;
    private readonly ILogger<MapsContentController> _log;

    public MapsContentController(
        IHttpClientFactory httpFactory,
        InternalTokenStore internalToken,
        IOptions<SimpleLiteOptions> sl,
        ILogger<MapsContentController> log)
    {
        _httpFactory = httpFactory;
        _internalToken = internalToken;
        _sl = sl.Value;
        _log = log;
    }

    [HttpGet("{name}/content")]
    public async Task<IActionResult> GetContent(string name, CancellationToken ct)
    {
        if (string.IsNullOrWhiteSpace(name)
            || name.Contains("..", StringComparison.Ordinal)
            || name.IndexOfAny(['/', '\\', ':', '*', '?', '"', '<', '>', '|']) >= 0)
        {
            return BadRequest(new { message = "地图名称非法" });
        }

        try
        {
            var directory = await FetchMapsDirectoryAsync(ct);
            if (string.IsNullOrWhiteSpace(directory))
                return StatusCode(503, new { message = "无法从 SimpleLite 获取地图目录" });

            var fileName = name.EndsWith(".json", StringComparison.OrdinalIgnoreCase) ? name : $"{name}.json";
            var fullPath = Path.GetFullPath(Path.Combine(directory, fileName));
            var root = Path.GetFullPath(directory);
            if (!fullPath.StartsWith(root, StringComparison.OrdinalIgnoreCase))
                return BadRequest(new { message = "路径校验失败" });

            if (!System.IO.File.Exists(fullPath))
                return NotFound(new { message = $"地图文件不存在：{fileName}" });

            var content = await System.IO.File.ReadAllTextAsync(fullPath, ct);
            // 不返回 fullPath：避免向前端泄露服务器目录结构。
            return Ok(new
            {
                name,
                fileName,
                content
            });
        }
        catch (Exception ex)
        {
            _log.LogWarning(ex, "读取地图 JSON 失败 name={Name}", name);
            return StatusCode(500, new { message = $"读取地图 JSON 失败：{ex.Message}" });
        }
    }

    private async Task<string?> FetchMapsDirectoryAsync(CancellationToken ct)
    {
        var client = _httpFactory.CreateClient();
        client.Timeout = TimeSpan.FromSeconds(8);
        var url = $"http://127.0.0.1:{_sl.ProjectionPort}/projection/map-edit/maps";
        using var msg = new HttpRequestMessage(HttpMethod.Get, url);
        if (!string.IsNullOrEmpty(_internalToken.Token))
            msg.Headers.TryAddWithoutValidation("X-Platform-Internal-Token", _internalToken.Token);

        using var resp = await client.SendAsync(msg, ct);
        var body = await resp.Content.ReadAsStringAsync(ct);
        if (!resp.IsSuccessStatusCode)
            throw new InvalidOperationException($"SimpleLite maps 列表返回 {(int)resp.StatusCode}");

        using var doc = JsonDocument.Parse(body);
        var root = doc.RootElement;
        if (root.TryGetProperty("success", out var ok) && ok.ValueKind == JsonValueKind.False)
        {
            var message = root.TryGetProperty("message", out var m) ? m.GetString() : "maps 列表失败";
            throw new InvalidOperationException(message ?? "maps 列表失败");
        }

        JsonElement data = root;
        if (root.TryGetProperty("data", out var d) && d.ValueKind == JsonValueKind.Object)
            data = d;

        if (data.TryGetProperty("directory", out var dir) && dir.ValueKind == JsonValueKind.String)
            return dir.GetString();

        return null;
    }
}
