using System.Text.Json.Serialization;

namespace AxCopilot.Services.Agent.Sdk;

// ═══════════════════════════════════════════════════════════════════
//  Phase 31-A: SDK 제어 프로토콜 메시지 정의
//  CC의 JSON 스트리밍 프로토콜과 동등한 양방향 메시지 체계.
//  Host(IDE/스크립트) ↔ CLI(AgentSdkServer) 간 stdin/stdout JSON 통신.
// ═══════════════════════════════════════════════════════════════════

#region ── Host → CLI 요청 ──

/// <summary>SDK 제어 요청 타입.</summary>
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum SdkControlRequestType
{
    /// <summary>세션 초기화. 커스텀 에이전트, 훅 콜백 등록.</summary>
    Initialize,
    /// <summary>사용자 메시지 전송.</summary>
    UserMessage,
    /// <summary>권한 모드 변경.</summary>
    SetPermissionMode,
    /// <summary>모델 전환.</summary>
    SetModel,
    /// <summary>현재 턴 중단.</summary>
    Interrupt,
    /// <summary>컨텍스트 사용량 조회.</summary>
    GetContextUsage,
    /// <summary>파일 변경 되돌리기.</summary>
    RewindFiles,
    /// <summary>도구 사용 허가 응답 (CLI → Host 질의에 대한 답변).</summary>
    CanUseToolResponse,
    /// <summary>세션 종료.</summary>
    Terminate,
}

/// <summary>Host → CLI 제어 요청.</summary>
public class SdkControlRequest
{
    [JsonPropertyName("type")]
    public SdkControlRequestType Type { get; set; }

    [JsonPropertyName("id")]
    public string Id { get; set; } = Guid.NewGuid().ToString("N")[..8];

    [JsonPropertyName("payload")]
    public System.Text.Json.JsonElement? Payload { get; set; }
}

/// <summary>Initialize 요청 페이로드.</summary>
public class SdkInitializePayload
{
    [JsonPropertyName("workFolder")]
    public string? WorkFolder { get; set; }

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

    [JsonPropertyName("permissionMode")]
    public string? PermissionMode { get; set; }

    [JsonPropertyName("systemPrompt")]
    public string? SystemPrompt { get; set; }

    [JsonPropertyName("customAgents")]
    public List<CustomAgentDefinition>? CustomAgents { get; set; }

    [JsonPropertyName("maxTurns")]
    public int? MaxTurns { get; set; }

    [JsonPropertyName("disabledTools")]
    public List<string>? DisabledTools { get; set; }

    [JsonPropertyName("hookCallbacks")]
    public List<string>? HookCallbacks { get; set; }
}

/// <summary>UserMessage 요청 페이로드.</summary>
public class SdkUserMessagePayload
{
    [JsonPropertyName("message")]
    public string Message { get; set; } = "";

    [JsonPropertyName("attachments")]
    public List<string>? Attachments { get; set; }
}

#endregion

#region ── CLI → Host 응답/이벤트 ──

/// <summary>SDK 메시지 타입 (CLI → Host).</summary>
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum SdkMessageType
{
    /// <summary>초기화 완료 응답.</summary>
    InitializeResult,
    /// <summary>어시스턴트 텍스트 토큰 (스트리밍).</summary>
    AssistantToken,
    /// <summary>어시스턴트 메시지 완료.</summary>
    AssistantMessage,
    /// <summary>도구 호출 시작.</summary>
    ToolUseStart,
    /// <summary>도구 실행 진행 상황.</summary>
    ToolProgress,
    /// <summary>도구 실행 결과.</summary>
    ToolResult,
    /// <summary>세션/턴 최종 결과.</summary>
    SessionResult,
    /// <summary>훅 이벤트 (콜백 요청).</summary>
    HookEvent,
    /// <summary>도구 사용 허가 요청 (CLI → Host).</summary>
    CanUseTool,
    /// <summary>일반 알림.</summary>
    Notification,
    /// <summary>오류.</summary>
    Error,
}

/// <summary>CLI → Host 메시지.</summary>
public class SdkMessage
{
    [JsonPropertyName("type")]
    public SdkMessageType Type { get; set; }

    [JsonPropertyName("id")]
    public string? RequestId { get; set; }

    [JsonPropertyName("data")]
    public object? Data { get; set; }

    [JsonPropertyName("timestamp")]
    public DateTime Timestamp { get; set; } = DateTime.UtcNow;
}

/// <summary>AssistantToken 데이터.</summary>
public class SdkTokenData
{
    [JsonPropertyName("text")]
    public string Text { get; set; } = "";
}

/// <summary>ToolUseStart 데이터.</summary>
public class SdkToolUseStartData
{
    [JsonPropertyName("toolName")]
    public string ToolName { get; set; } = "";

    [JsonPropertyName("input")]
    public object? Input { get; set; }
}

/// <summary>ToolResult 데이터.</summary>
public class SdkToolResultData
{
    [JsonPropertyName("toolName")]
    public string ToolName { get; set; } = "";

    [JsonPropertyName("success")]
    public bool Success { get; set; }

    [JsonPropertyName("output")]
    public string Output { get; set; } = "";

    [JsonPropertyName("filePath")]
    public string? FilePath { get; set; }

    [JsonPropertyName("elapsedMs")]
    public long ElapsedMs { get; set; }
}

/// <summary>SessionResult 데이터.</summary>
public class SdkSessionResultData
{
    [JsonPropertyName("response")]
    public string Response { get; set; } = "";

    [JsonPropertyName("totalToolCalls")]
    public int TotalToolCalls { get; set; }

    [JsonPropertyName("iterations")]
    public int Iterations { get; set; }

    [JsonPropertyName("inputTokens")]
    public int InputTokens { get; set; }

    [JsonPropertyName("outputTokens")]
    public int OutputTokens { get; set; }

    [JsonPropertyName("durationMs")]
    public long DurationMs { get; set; }
}

/// <summary>CanUseTool 데이터 (CLI → Host 질의).</summary>
public class SdkCanUseToolData
{
    [JsonPropertyName("toolName")]
    public string ToolName { get; set; } = "";

    [JsonPropertyName("filePath")]
    public string? FilePath { get; set; }

    [JsonPropertyName("input")]
    public object? Input { get; set; }
}

/// <summary>Error 데이터.</summary>
public class SdkErrorData
{
    [JsonPropertyName("code")]
    public string Code { get; set; } = "UNKNOWN";

    [JsonPropertyName("message")]
    public string Message { get; set; } = "";
}

#endregion

#region ── 커스텀 에이전트 정의 ──

/// <summary>
/// Phase 31-C: SDK에서 정의하는 커스텀 에이전트.
/// Initialize 요청 시 등록하면 delegate 도구에서 사용 가능.
/// </summary>
public class CustomAgentDefinition
{
    [JsonPropertyName("name")]
    public string Name { get; set; } = "";

    [JsonPropertyName("description")]
    public string Description { get; set; } = "";

    [JsonPropertyName("prompt")]
    public string Prompt { get; set; } = "";

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

    [JsonPropertyName("allowedTools")]
    public List<string>? AllowedTools { get; set; }

    [JsonPropertyName("disallowedTools")]
    public List<string>? DisallowedTools { get; set; }

    [JsonPropertyName("maxTurns")]
    public int MaxTurns { get; set; } = 10;

    [JsonPropertyName("permissionMode")]
    public string? PermissionMode { get; set; }
}

#endregion
