using System.Diagnostics;
using System.IO;
using System.Text;
using AxCopilot.Models;

namespace AxCopilot.Services.Agent.SlashCommands;

/// <summary>Phase 22: /review — AI 코드 리뷰.</summary>
public class ReviewCommand : ISlashCommand
{
    public string Name => "review";
    public string[] Aliases => Array.Empty<string>();
    public string Description => "현재 브랜치의 변경 사항을 AI로 리뷰합니다";
    public string? ArgumentHint => "[브랜치명 또는 diff 범위]";
    public bool RequiresActiveSession => false;

    public async Task ExecuteAsync(string arguments, IAgentChatContext ctx, CancellationToken ct)
    {
        var workDir = ctx.WorkFolder;
        if (string.IsNullOrEmpty(workDir) || !Directory.Exists(workDir))
        {
            await ctx.SendSystemMessageAsync("작업 폴더가 설정되지 않았습니다.");
            return;
        }

        await ctx.SendSystemMessageAsync("코드 리뷰를 준비하고 있습니다...");

        // diff 가져오기
        var diffArgs = string.IsNullOrWhiteSpace(arguments)
            ? "diff HEAD"
            : $"diff {arguments.Trim()}";

        var diff = await RunGitAsync(diffArgs, workDir, ct);
        if (string.IsNullOrWhiteSpace(diff))
        {
            diff = await RunGitAsync("diff --cached", workDir, ct);
        }

        if (string.IsNullOrWhiteSpace(diff))
        {
            await ctx.SendSystemMessageAsync("리뷰할 변경 사항이 없습니다.");
            return;
        }

        var truncated = diff.Length > 12000 ? diff[..12000] + "\n...(이하 생략)" : diff;
        var prompt = $"""
            아래 코드 변경 사항을 리뷰하세요. 한국어로 작성하세요.

            ## 리뷰 포함 사항
            1. **변경 사항 개요** — 무엇이 변경되었는지 요약
            2. **코드 품질** — 가독성, 명명, 중복 등
            3. **잠재적 버그** — null 참조, 경계 조건, 리소스 누수
            4. **보안 이슈** — 인젝션, 하드코딩된 자격증명 등
            5. **개선 제안** — 구체적 코드 예시 포함

            ```diff
            {truncated}
            ```
            """;

        try
        {
            var messages = new List<ChatMessage>
            {
                new() { Role = "user", Content = prompt }
            };
            var review = await ctx.Llm.SendAsync(messages, ct);
            await ctx.SendSystemMessageAsync($"## 코드 리뷰\n{review}");
        }
        catch (Exception ex)
        {
            await ctx.SendSystemMessageAsync($"리뷰 생성 실패: {ex.Message}");
        }
    }

    private static async Task<string> RunGitAsync(string args, string workDir, CancellationToken ct)
    {
        try
        {
            var psi = new ProcessStartInfo
            {
                FileName = "git",
                Arguments = args,
                WorkingDirectory = workDir,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                CreateNoWindow = true,
                StandardOutputEncoding = Encoding.UTF8,
            };
            using var proc = Process.Start(psi);
            if (proc == null) return "";
            var output = await proc.StandardOutput.ReadToEndAsync(ct);
            await proc.WaitForExitAsync(ct);
            return output;
        }
        catch (Exception) { return ""; }
    }
}
