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

namespace AxCopilot.Services.Agent;

/// <summary>
/// 이미지를 분석하여 내용 설명, 텍스트 추출, 차트 데이터 해석을 수행하는 도구.
/// LLM 멀티모달 API를 활용합니다.
/// </summary>
public class ImageAnalyzeTool : IAgentTool
{
    public string Name => "image_analyze";
    public string Description =>
        "Analyze an image using LLM multimodal vision. " +
        "Tasks: describe (general description), extract_text (OCR-like text extraction), " +
        "extract_data (extract structured data like tables/charts from image), " +
        "compare (compare two images and describe differences).";

    public ToolParameterSchema Parameters => new()
    {
        Properties = new()
        {
            ["image_path"] = new()
            {
                Type = "string",
                Description = "Path to the image file (.png, .jpg, .jpeg, .bmp, .gif, .webp)."
            },
            ["task"] = new()
            {
                Type = "string",
                Description = "Analysis task: describe, extract_text, extract_data, compare. Default: describe",
                Enum = ["describe", "extract_text", "extract_data", "compare"]
            },
            ["compare_path"] = new()
            {
                Type = "string",
                Description = "Path to second image for comparison (only used with task=compare)."
            },
            ["question"] = new()
            {
                Type = "string",
                Description = "Optional specific question about the image."
            },
            ["language"] = new()
            {
                Type = "string",
                Description = "Response language: ko (Korean), en (English). Default: ko"
            },
        },
        Required = ["image_path"]
    };

    public async Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct)
    {
        var imagePath = args.GetProperty("image_path").GetString() ?? "";
        var task = args.TryGetProperty("task", out var taskEl) ? taskEl.GetString() ?? "describe" : "describe";
        var question = args.TryGetProperty("question", out var qEl) ? qEl.GetString() ?? "" : "";
        var language = args.TryGetProperty("language", out var langEl) ? langEl.GetString() ?? "ko" : "ko";

        var fullPath = FileReadTool.ResolvePath(imagePath, context.WorkFolder);
        if (!context.IsPathAllowed(fullPath))
            return ToolResult.Fail($"경로 접근 차단: {fullPath}");
        if (!File.Exists(fullPath))
            return ToolResult.Fail($"파일 없음: {fullPath}");

        // 지원 이미지 형식 확인
        var ext = Path.GetExtension(fullPath).ToLowerInvariant();
        if (!IsImageExtension(ext))
            return ToolResult.Fail($"지원하지 않는 이미지 형식: {ext}");

        // 이미지를 base64로 인코딩
        var imageBytes = await File.ReadAllBytesAsync(fullPath, ct);
        var base64 = Convert.ToBase64String(imageBytes);
        var mimeType = ext switch
        {
            ".png" => "image/png",
            ".jpg" or ".jpeg" => "image/jpeg",
            ".gif" => "image/gif",
            ".webp" => "image/webp",
            ".bmp" => "image/bmp",
            _ => "image/png"
        };

        // 파일 크기 제한 (10MB)
        if (imageBytes.Length > 10 * 1024 * 1024)
            return ToolResult.Fail("이미지 크기가 10MB를 초과합니다.");

        // 비교 모드: 두 번째 이미지
        string? compareBase64 = null;
        string? compareMime = null;
        if (task == "compare" && args.TryGetProperty("compare_path", out var cpEl))
        {
            var comparePath = FileReadTool.ResolvePath(cpEl.GetString() ?? "", context.WorkFolder);
            if (File.Exists(comparePath) && context.IsPathAllowed(comparePath))
            {
                var compareBytes = await File.ReadAllBytesAsync(comparePath, ct);
                compareBase64 = Convert.ToBase64String(compareBytes);
                var compareExt = Path.GetExtension(comparePath).ToLowerInvariant();
                compareMime = compareExt switch
                {
                    ".png" => "image/png",
                    ".jpg" or ".jpeg" => "image/jpeg",
                    ".gif" => "image/gif",
                    ".webp" => "image/webp",
                    _ => "image/png"
                };
            }
        }

        // 프롬프트 구성
        var langPrompt = language == "en" ? "Respond in English." : "한국어로 응답하세요.";
        var prompt = task switch
        {
            "extract_text" =>
                $"이 이미지에서 모든 텍스트를 추출하세요. 원본 레이아웃을 최대한 유지하세요. {langPrompt}",
            "extract_data" =>
                $"이 이미지에서 구조화된 데이터를 추출하세요. 테이블, 차트, 그래프 등의 데이터를 " +
                $"CSV 또는 JSON 형식으로 변환하세요. 차트의 경우 각 항목의 값을 추정하세요. {langPrompt}",
            "compare" =>
                $"두 이미지를 비교하고 차이점을 설명하세요. {langPrompt}",
            _ => string.IsNullOrEmpty(question)
                ? $"이 이미지의 내용을 상세하게 설명하세요. 주요 요소, 텍스트, 레이아웃, 색상 등을 포함하세요. {langPrompt}"
                : $"{question} {langPrompt}"
        };

        // LLM에 이미지 분석 요청을 위한 결과 생성
        // 실제 LLM 호출은 에이전트 루프에서 수행하므로, 여기서는 이미지 정보와 프롬프트를 반환
        var info = new System.Text.StringBuilder();
        info.AppendLine($"🖼 이미지 분석 준비 완료");
        info.AppendLine($"  파일: {Path.GetFileName(fullPath)}");
        info.AppendLine($"  크기: {imageBytes.Length / 1024}KB");
        info.AppendLine($"  형식: {mimeType}");
        info.AppendLine($"  작업: {task}");
        info.AppendLine();
        info.AppendLine($"[IMAGE_BASE64:{mimeType}]{base64}[/IMAGE_BASE64]");

        if (compareBase64 != null)
            info.AppendLine($"[IMAGE_BASE64:{compareMime}]{compareBase64}[/IMAGE_BASE64]");

        info.AppendLine();
        info.AppendLine($"분석 프롬프트: {prompt}");

        return ToolResult.Ok(info.ToString());
    }

    private static bool IsImageExtension(string ext)
    {
        return ext is ".png" or ".jpg" or ".jpeg" or ".gif" or ".bmp" or ".webp";
    }
}
