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

namespace AxCopilot.Services.Agent.SlashCommands;

/// <summary>Phase 22: /commit — AI 커밋 메시지 생성.</summary>
public class CommitCommand : ISlashCommand
{
    public string Name => "commit";
    public string[] Aliases => Array.Empty<string>();
    public string Description => "AI가 생성한 메시지로 git 커밋을 만듭니다";
    public string? ArgumentHint => null;
    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;
        }

        // 1. git status 확인
        var statusResult = await RunGitAsync("status --porcelain", workDir, ct);
        if (string.IsNullOrWhiteSpace(statusResult))
        {
            await ctx.SendSystemMessageAsync("커밋할 변경 사항이 없습니다.");
            return;
        }

        // 2. git diff 가져오기
        var diffResult = await RunGitAsync("diff --cached", workDir, ct);
        if (string.IsNullOrWhiteSpace(diffResult))
            diffResult = await RunGitAsync("diff", workDir, ct);

        if (string.IsNullOrWhiteSpace(diffResult))
        {
            await ctx.SendSystemMessageAsync("diff가 비어 있습니다. `git add`를 먼저 실행하세요.");
            return;
        }

        // 3. LLM에게 커밋 메시지 생성 요청
        var truncatedDiff = diffResult.Length > 8000 ? diffResult[..8000] + "\n..." : diffResult;
        var prompt = $"""
            아래 git diff를 분석하고 간결한 커밋 메시지를 작성하세요.
            - 첫 줄: 50자 이내 제목 (무엇을 왜)
            - 빈 줄 후 본문: 변경 이유와 영향 (필요시)
            - 커밋 메시지만 출력하세요 (설명 없이)

            git status:
            {statusResult}

            diff:
            {truncatedDiff}
            """;

        await ctx.SendSystemMessageAsync("커밋 메시지를 생성하고 있습니다...");

        try
        {
            var messages = new List<ChatMessage>
            {
                new() { Role = "user", Content = prompt }
            };
            var commitMsg = await ctx.Llm.SendAsync(messages, ct);
            commitMsg = commitMsg.Trim().Trim('`').Trim();

            await ctx.SendSystemMessageAsync(
                $"## 제안된 커밋 메시지\n```\n{commitMsg}\n```\n\n이 메시지로 커밋하려면 `yes`를 입력하세요.");
        }
        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 "";
        }
    }
}
