using System.Text.Json;
using Hc900Crawler.Infrastructure.Mcp;
using Hc900Crawler.Core.Application.DTOs;

namespace Hc900Crawler.Core.Application.Services;

public interface IPidGraphService
{
    Task<PidGraphBuildResult> BuildPidGraphAsync(string filepath, Action<double, string>? progressHandler = null, CancellationToken ct = default);
    Task<PidImpactResult> AnalyzeImpactAsync(string graphId, string nodeId, CancellationToken ct = default);
}

public class PidGraphService : IPidGraphService
{
    private readonly McpClient _mcpClient;
    private readonly ILogger<PidGraphService> _logger;

    public PidGraphService(McpClient mcpClient, ILogger<PidGraphService> logger)
    {
        _mcpClient = mcpClient;
        _logger = logger;
    }

    public async Task<PidGraphBuildResult> BuildPidGraphAsync(string filepath, Action<double, string>? progressHandler = null, CancellationToken ct = default)
    {
        try
        {
            progressHandler?.Invoke(10, "MCP 서버에 추출 요청 전송 중...");
            
            var args = new Dictionary<string, object>
            {
                ["filepath"] = filepath
            };

            progressHandler?.Invoke(30, "도면 기하학적 데이터 추출 중 (Phase 1)...");
            var jsonResponse = await _mcpClient.CallToolAsync("build_pid_graph_parallel", args, ct);
            
            progressHandler?.Invoke(70, "지능형 태그 매핑 및 위상 분석 중 (Phase 2 & 3)...");
            var result = JsonSerializer.Deserialize<PidGraphBuildResult>(jsonResponse, new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            });

            progressHandler?.Invoke(90, "최종 그래프 구조 생성 및 저장 중...");
            return result ?? throw new Exception("Failed to deserialize MCP response");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error building PID graph for file {Filepath}", filepath);
            return new PidGraphBuildResult { Success = false, Error = ex.Message };
        }
    }

    public async Task<PidImpactResult> AnalyzeImpactAsync(string graphId, string nodeId, CancellationToken ct = default)
    {
        try
        {
            var args = new Dictionary<string, object>
            {
                ["graph_id"] = graphId,
                ["start_node_id"] = nodeId
            };

            var jsonResponse = await _mcpClient.CallToolAsync("analyze_pid_impact", args, ct);
            var result = JsonSerializer.Deserialize<PidImpactResult>(jsonResponse, new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            });

            return result ?? throw new Exception("Failed to deserialize MCP response");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error analyzing impact for graph {GraphId} node {NodeId}", graphId, nodeId);
            return new PidImpactResult { Success = false, Error = ex.Message };
        }
    }
}

public class PidGraphBuildResult
{
    public bool Success { get; set; }
    public string? GraphId { get; set; }
    public string? GraphPath { get; set; }
    public int Nodes { get; set; }
    public int Edges { get; set; }
    public string? Error { get; set; }
}

public class PidImpactResult
{
    public bool Success { get; set; }
    public string? StartNode { get; set; }
    public Dictionary<string, int>? ImpactedNodes { get; set; }
    public List<List<string>>? Paths { get; set; }
    public string? Error { get; set; }
}
