using System.IO;
using System.Text;
using System.Text.Json;

namespace AxCopilot.Services.Agent;

/// <summary>
/// CSS/SVG 기반 차트를 HTML 파일로 생성하는 스킬.
/// bar, line, pie(donut), radar, area 차트를 지원하며 TemplateService 무드 스타일을 적용합니다.
/// </summary>
public partial class ChartSkill : IAgentTool
{
    public string Name => "chart_create";
    public string Description =>
        "Create a styled HTML chart document with CSS/SVG-based charts. " +
        "Supports chart types: bar, horizontal_bar, stacked_bar, line, area, pie, donut, radar, progress, comparison. " +
        "Multiple charts can be placed in one document using the 'charts' array. " +
        "Applies design mood from TemplateService (modern, professional, creative, etc.).";

    public ToolParameterSchema Parameters => new()
    {
        Properties = new()
        {
            ["path"] = new() { Type = "string", Description = "Output file path (.html). Relative to work folder." },
            ["title"] = new() { Type = "string", Description = "Document title" },
            ["charts"] = new()
            {
                Type = "array",
                Description = "Array of chart objects. Each chart: " +
                    "{\"type\": \"bar|horizontal_bar|stacked_bar|line|area|pie|donut|radar|progress|comparison\", " +
                    "\"title\": \"Chart Title\", " +
                    "\"labels\": [\"A\",\"B\",\"C\"], " +
                    "\"datasets\": [{\"name\": \"Series1\", \"values\": [10,20,30], \"color\": \"#4B5EFC\"}], " +
                    "\"unit\": \"%\"}",
                Items = new ToolProperty { Type = "object" },
            },
            ["mood"] = new() { Type = "string", Description = "Design mood: modern, professional, creative, dark, dashboard, etc. Default: dashboard" },
            ["layout"] = new() { Type = "string", Description = "Chart layout: 'single' (one per row) or 'grid' (2-column grid). Default: single" },
        },
        Required = ["path", "title", "charts"]
    };

    // 기본 차트 팔레트
    private static readonly string[] Palette =
    [
        "#4B5EFC", "#10B981", "#F59E0B", "#EF4444", "#8B5CF6",
        "#06B6D4", "#EC4899", "#84CC16", "#F97316", "#6366F1",
    ];

    public async Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct)
    {
        var path = args.GetProperty("path").GetString() ?? "chart.html";
        var title = args.GetProperty("title").GetString() ?? "Chart";
        var mood = args.TryGetProperty("mood", out var m) ? m.GetString() ?? "dashboard" : "dashboard";
        var layout = args.TryGetProperty("layout", out var l) ? l.GetString() ?? "single" : "single";

        var fullPath = FileReadTool.ResolvePath(path, context.WorkFolder);
        if (context.ActiveTab == "Cowork") fullPath = AgentContext.EnsureTimestampedPath(fullPath);
        if (!fullPath.EndsWith(".html", StringComparison.OrdinalIgnoreCase))
            fullPath += ".html";

        if (!context.IsPathAllowed(fullPath))
            return ToolResult.Fail($"경로 접근 차단: {fullPath}");
        if (!await context.CheckWritePermissionAsync(Name, fullPath))
            return ToolResult.Fail($"쓰기 권한 거부: {fullPath}");

        var dir = Path.GetDirectoryName(fullPath);
        if (!string.IsNullOrEmpty(dir)) Directory.CreateDirectory(dir);

        if (!args.TryGetProperty("charts", out var chartsEl) || chartsEl.ValueKind != JsonValueKind.Array)
            return ToolResult.Fail("charts 파라미터가 필요합니다 (배열 형식).");

        var chartCount = chartsEl.GetArrayLength();
        var body = new StringBuilder();

        body.AppendLine($"<h1>{Escape(title)}</h1>");

        if (layout == "grid" && chartCount > 1)
            body.AppendLine("<div class=\"grid-2\">");

        int chartIdx = 0;
        foreach (var chartEl in chartsEl.EnumerateArray())
        {
            var chartHtml = RenderChart(chartEl, chartIdx);
            body.AppendLine("<div class=\"card\" style=\"margin-bottom:20px;\">");
            body.AppendLine(chartHtml);
            body.AppendLine("</div>");
            chartIdx++;
        }

        if (layout == "grid" && chartCount > 1)
            body.AppendLine("</div>");

        var css = TemplateService.GetCss(mood) + "\n" + ChartCss;

        var html = $@"<!DOCTYPE html>
<html lang=""ko"">
<head>
<meta charset=""UTF-8"">
<meta name=""viewport"" content=""width=device-width, initial-scale=1.0"">
<title>{Escape(title)}</title>
<style>
{css}
</style>
</head>
<body>
<div class=""container"">
{body}
</div>
</body>
</html>";

        await File.WriteAllTextAsync(fullPath, html, Encoding.UTF8, ct);
        return ToolResult.Ok($"차트 문서 생성 완료: {fullPath} ({chartCount}개 차트)", fullPath);
    }

    private string RenderChart(JsonElement chart, int idx)
    {
        var type = chart.TryGetProperty("type", out var t) ? t.GetString() ?? "bar" : "bar";
        var chartTitle = chart.TryGetProperty("title", out var ct) ? ct.GetString() ?? "" : "";
        var unit = chart.TryGetProperty("unit", out var u) ? u.GetString() ?? "" : "";
        var labels = ParseStringArray(chart, "labels");
        var datasets = ParseDatasets(chart);

        var sb = new StringBuilder();
        if (!string.IsNullOrEmpty(chartTitle))
            sb.AppendLine($"<h3 style=\"margin-bottom:12px;\">{Escape(chartTitle)}</h3>");

        switch (type)
        {
            case "bar":
                sb.Append(RenderBarChart(labels, datasets, unit, false));
                break;
            case "horizontal_bar":
                sb.Append(RenderBarChart(labels, datasets, unit, true));
                break;
            case "stacked_bar":
                sb.Append(RenderStackedBar(labels, datasets, unit));
                break;
            case "line":
            case "area":
                sb.Append(RenderLineChart(labels, datasets, unit, type == "area"));
                break;
            case "pie":
            case "donut":
                sb.Append(RenderPieChart(labels, datasets, type == "donut"));
                break;
            case "progress":
                sb.Append(RenderProgressChart(labels, datasets, unit));
                break;
            case "comparison":
                sb.Append(RenderComparisonChart(labels, datasets, unit));
                break;
            case "radar":
                sb.Append(RenderRadarChart(labels, datasets));
                break;
            default:
                sb.Append(RenderBarChart(labels, datasets, unit, false));
                break;
        }

        // 범례
        if (datasets.Count > 1)
        {
            sb.AppendLine("<div class=\"chart-legend\">");
            foreach (var ds in datasets)
                sb.AppendLine($"<span class=\"legend-item\"><span class=\"legend-dot\" style=\"background:{ds.Color}\"></span>{Escape(ds.Name)}</span>");
            sb.AppendLine("</div>");
        }

        return sb.ToString();
    }

}
