using System.Text.Json.Serialization;

namespace AxCopilot.Services.Agent;

/// <summary>훅 이벤트 종류. 기존 pre/post 타이밍 외 세션·파일·권한 이벤트 추가.</summary>
public enum HookEventKind
{
    // 기존 (Timing 기반에서 이벤트 기반으로 통합)
    PreToolUse,
    PostToolUse,
    PostToolUseFailure,  // Phase 25: 도구 실행 실패 후 (CC 동등)
    AgentStop,

    // 신규 Phase 17-C
    Stop,                // Phase 25: 모델 턴 종료 직전 (CC 동등, exit 2=계속)
    UserPromptSubmit,
    PreCompact,
    PostCompact,
    FileChanged,
    CwdChanged,
    SessionStart,
    SessionEnd,
    ConfigChange,
    PermissionRequest,
    PreSkillExecute,
    PostSkillExecute,
    SubagentStart,
    SubagentStop,
}

/// <summary>훅 실행 방식.</summary>
public enum HookExecutionMode
{
    Command,  // 외부 스크립트 (bat/ps1/cmd) — 기존
    Http,     // HTTP POST 웹훅
    Prompt,   // LLM 검사 (소형 모델)
    Agent,    // 미니 에이전트 루프
}

/// <summary>확장된 훅 정의 (Phase 17-C). 기존 AgentHookEntry와 병행.</summary>
public class ExtendedHookEntry
{
    [JsonPropertyName("name")]
    public string Name { get; set; } = "";

    [JsonPropertyName("event")]
    public HookEventKind Event { get; set; } = HookEventKind.PostToolUse;

    [JsonPropertyName("matcher")]
    public string? Matcher { get; set; }  // 도구 이름 패턴 (* = 모두)

    [JsonPropertyName("mode")]
    public HookExecutionMode Mode { get; set; } = HookExecutionMode.Command;

    // Command 모드
    [JsonPropertyName("script_path")]
    public string? ScriptPath { get; set; }

    [JsonPropertyName("arguments")]
    public string? Arguments { get; set; }

    // Http 모드
    [JsonPropertyName("url")]
    public string? Url { get; set; }

    [JsonPropertyName("headers")]
    public Dictionary<string, string> Headers { get; set; } = new();

    // Prompt 모드
    [JsonPropertyName("prompt")]
    public string? Prompt { get; set; }

    [JsonPropertyName("model")]
    public string? Model { get; set; }

    // 공통 속성
    [JsonPropertyName("enabled")]
    public bool Enabled { get; set; } = true;

    [JsonPropertyName("once")]
    public bool Once { get; set; } = false;        // 한 번 실행 후 비활성화

    [JsonPropertyName("async")]
    public bool IsAsync { get; set; } = false;     // 비동기 (결과 기다리지 않음)

    /// <summary>Phase 25-B: 비동기 + exit code 2 시 대화 재활성화. CC asyncRewake 동등.</summary>
    [JsonPropertyName("async_rewake")]
    public bool AsyncRewake { get; set; } = false;

    [JsonPropertyName("timeout_seconds")]
    public int TimeoutSeconds { get; set; } = 30;

    [JsonPropertyName("status_message")]
    public string? StatusMessage { get; set; }     // 실행 중 표시 메시지

    [JsonPropertyName("condition")]
    public string? Condition { get; set; }          // 조건 (예: "permission_mode == acceptEdits")

    [JsonPropertyName("watch_paths")]
    public List<string> WatchPaths { get; set; } = new();  // SessionStart 훅의 감시 경로
}

/// <summary>훅 실행 컨텍스트.</summary>
public class HookContext
{
    public HookEventKind Event { get; init; }
    public string? ToolName { get; init; }
    public string? ToolInput { get; init; }
    public string? ToolOutput { get; init; }
    public bool ToolSuccess { get; init; }
    public string? UserMessage { get; init; }
    public string? ChangedFilePath { get; init; }
    public string SessionId { get; init; } = "";
    public string WorkFolder { get; init; } = "";
}

/// <summary>확장된 훅 실행 결과.</summary>
public record ExtendedHookResult
{
    public bool Block { get; init; } = false;
    public string? BlockReason { get; init; }
    public string? AdditionalContext { get; init; }   // 시스템 프롬프트에 추가
    public string? UpdatedInput { get; init; }         // 수정된 도구 입력
    public ExtendedPermissionDecision? PermissionDecision { get; init; }
    public IReadOnlyList<string>? WatchPaths { get; init; }
    public string? StatusMessage { get; init; }
    public bool Once { get; init; } = false;           // 이 훅을 한 번만 실행 후 비활성화
}

public enum ExtendedPermissionDecision { Allow, Deny, Ask }
