use serde::{Deserialize, Serialize};
use std::collections::HashMap;

// --- Core entity types ---

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Entity {
    pub id: String,
    #[serde(rename = "type")]
    pub entity_type: String,
    pub owner: String,
    pub name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub metadata: Option<HashMap<String, serde_json::Value>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub relations: Option<Vec<RelationRef>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub version: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RelationRef {
    #[serde(rename = "type")]
    pub relation_type: String,
    #[serde(rename = "targetId")]
    pub target_id: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EntityContent {
    pub text: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub raw: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub encoding: Option<String>,
}

// --- Enums ---

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum WriteConsistency {
    #[serde(rename = "strong")]
    Strong,
    #[serde(rename = "eventual")]
    Eventual,
}

// --- Protocol envelopes ---

#[derive(Debug, Clone, Serialize)]
pub(crate) struct AuthRequest {
    #[serde(rename = "protocolVersion")]
    pub protocol_version: String,
    pub op: String,
    pub username: String,
    pub password: String,
}

#[derive(Debug, Clone, Deserialize)]
#[allow(dead_code)]
pub(crate) struct AuthResponse {
    #[serde(rename = "protocolVersion")]
    pub protocol_version: String,
    pub status: String,
    #[serde(default)]
    pub error: Option<crate::errors::ProtocolError>,
}

#[derive(Debug, Clone, Serialize)]
pub(crate) struct RequestEnvelope {
    #[serde(rename = "protocolVersion")]
    pub protocol_version: String,
    #[serde(rename = "requestId")]
    pub request_id: String,
    pub op: String,
    #[serde(rename = "idempotencyKey", skip_serializing_if = "Option::is_none")]
    pub idempotency_key: Option<String>,
    pub payload: serde_json::Value,
}

#[derive(Debug, Clone, Deserialize)]
#[allow(dead_code)]
pub(crate) struct ResponseEnvelope {
    #[serde(rename = "protocolVersion")]
    pub protocol_version: String,
    #[serde(rename = "requestId")]
    pub request_id: String,
    pub op: String,
    pub status: String,
    #[serde(default)]
    pub payload: Option<serde_json::Value>,
    #[serde(default)]
    pub error: Option<crate::errors::ProtocolError>,
}

// --- Health ---

#[derive(Debug, Clone, Deserialize)]
pub struct HealthResponse {
    pub status: String,
    #[serde(rename = "uptimeSeconds")]
    pub uptime_seconds: f64,
    #[serde(rename = "backendStatus")]
    pub backend_status: Option<HashMap<String, String>>,
}

// --- Index ---

#[derive(Debug, Clone, Serialize)]
pub struct IndexRequest {
    pub entity: Entity,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub content: Option<EntityContent>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub embedding: Option<Vec<f32>>,
    #[serde(rename = "categoryIds", skip_serializing_if = "Option::is_none")]
    pub category_ids: Option<Vec<String>>,
    #[serde(rename = "writeConsistency", skip_serializing_if = "Option::is_none")]
    pub write_consistency: Option<WriteConsistency>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct IndexResponse {
    pub id: String,
    pub version: String,
    #[serde(rename = "createdAt")]
    pub created_at: String,
    #[serde(rename = "writeConsistency")]
    pub write_consistency: Option<String>,
}

// --- Index Batch ---

#[derive(Debug, Clone, Serialize)]
pub struct IndexBatchItem {
    pub entity: Entity,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub content: Option<EntityContent>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub embedding: Option<Vec<f32>>,
    #[serde(rename = "categoryIds", skip_serializing_if = "Option::is_none")]
    pub category_ids: Option<Vec<String>>,
}

#[derive(Debug, Clone, Serialize, Default)]
pub struct IndexBatchOptions {
    #[serde(rename = "maxBatchSize", skip_serializing_if = "Option::is_none")]
    pub max_batch_size: Option<u32>,
    #[serde(rename = "maxPayloadBytes", skip_serializing_if = "Option::is_none")]
    pub max_payload_bytes: Option<u64>,
    #[serde(rename = "writeConsistency", skip_serializing_if = "Option::is_none")]
    pub write_consistency: Option<WriteConsistency>,
    #[serde(rename = "continueOnError", skip_serializing_if = "Option::is_none")]
    pub continue_on_error: Option<bool>,
}

#[derive(Debug, Clone, Serialize)]
pub struct IndexBatchRequest {
    pub items: Vec<IndexBatchItem>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub options: Option<IndexBatchOptions>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct IndexBatchResultItem {
    pub id: String,
    pub version: String,
    pub status: String,
    #[serde(default)]
    pub error: Option<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct IndexBatchResponse {
    pub results: Vec<IndexBatchResultItem>,
    #[serde(rename = "failedCount")]
    pub failed_count: u32,
    #[serde(rename = "totalCount")]
    pub total_count: u32,
}

// --- Get ---

#[derive(Debug, Clone, Serialize)]
pub struct GetRequest {
    pub id: String,
    #[serde(rename = "includeContent", skip_serializing_if = "Option::is_none")]
    pub include_content: Option<bool>,
    #[serde(rename = "includeRelations", skip_serializing_if = "Option::is_none")]
    pub include_relations: Option<bool>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct GetResponse {
    pub entity: Entity,
    #[serde(default)]
    pub content: Option<EntityContent>,
}

// --- Update ---

#[derive(Debug, Clone, Serialize, Default)]
pub struct UpdatePatch {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub metadata: Option<HashMap<String, serde_json::Value>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub relations: Option<Vec<RelationRef>>,
}

#[derive(Debug, Clone, Serialize, Default)]
pub struct ContentPatch {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub text: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub raw: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub encoding: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct UpdateRequest {
    pub id: String,
    #[serde(rename = "expectedVersion", skip_serializing_if = "Option::is_none")]
    pub expected_version: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub patch: Option<UpdatePatch>,
    #[serde(rename = "contentPatch", skip_serializing_if = "Option::is_none")]
    pub content_patch: Option<ContentPatch>,
    #[serde(rename = "writeConsistency", skip_serializing_if = "Option::is_none")]
    pub write_consistency: Option<WriteConsistency>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct UpdateResponse {
    pub id: String,
    pub version: String,
    #[serde(rename = "updatedAt")]
    pub updated_at: String,
}

// --- Delete ---

#[derive(Debug, Clone, Serialize)]
pub struct DeleteRequest {
    pub id: String,
    #[serde(rename = "expectedVersion", skip_serializing_if = "Option::is_none")]
    pub expected_version: Option<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct DeleteResponse {
    pub id: String,
    pub status: String,
    #[serde(rename = "deletedAt")]
    pub deleted_at: String,
}

// --- Delete Batch ---

#[derive(Debug, Clone, Serialize)]
pub struct DeleteBatchRequest {
    pub ids: Vec<String>,
    #[serde(rename = "continueOnError", skip_serializing_if = "Option::is_none")]
    pub continue_on_error: Option<bool>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct DeleteBatchResultItem {
    pub id: String,
    pub status: String,
    #[serde(default)]
    pub error: Option<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct DeleteBatchResponse {
    pub results: Vec<DeleteBatchResultItem>,
    #[serde(rename = "failedCount")]
    pub failed_count: u32,
    #[serde(rename = "totalCount")]
    pub total_count: u32,
}

// --- List Entities ---

#[derive(Debug, Clone, Serialize, Default)]
pub struct SearchFilters {
    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
    pub entity_type: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub category: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub owner: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub metadata: Option<HashMap<String, serde_json::Value>>,
}

#[derive(Debug, Clone, Serialize, Default)]
pub struct ListEntitiesRequest {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub filters: Option<SearchFilters>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<u32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub offset: Option<u32>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListEntitiesItem {
    pub id: String,
    #[serde(rename = "type")]
    pub entity_type: String,
    pub name: String,
    #[serde(default)]
    pub metadata: Option<HashMap<String, serde_json::Value>>,
    #[serde(default)]
    pub version: Option<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListEntitiesResponse {
    pub items: Vec<ListEntitiesItem>,
    pub total: u32,
    pub offset: u32,
}

// --- Semantic Search ---

#[derive(Debug, Clone, Serialize, Default)]
pub struct SearchOptions {
    #[serde(rename = "topK", skip_serializing_if = "Option::is_none")]
    pub top_k: Option<u32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub offset: Option<u32>,
    #[serde(rename = "expandGraph", skip_serializing_if = "Option::is_none")]
    pub expand_graph: Option<bool>,
    #[serde(rename = "graphHops", skip_serializing_if = "Option::is_none")]
    pub graph_hops: Option<u32>,
    #[serde(rename = "includeContentPreview", skip_serializing_if = "Option::is_none")]
    pub include_content_preview: Option<bool>,
    #[serde(rename = "includeRelations", skip_serializing_if = "Option::is_none")]
    pub include_relations: Option<bool>,
    #[serde(rename = "useKeyword", skip_serializing_if = "Option::is_none")]
    pub use_keyword: Option<bool>,
}

#[derive(Debug, Clone, Serialize)]
pub struct SemanticSearchRequest {
    pub text: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub filters: Option<SearchFilters>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub options: Option<SearchOptions>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct RelatedEntity {
    pub id: String,
    #[serde(rename = "type")]
    pub entity_type: String,
    pub name: String,
    #[serde(rename = "relationType")]
    pub relation_type: String,
    pub distance: i32,
}

#[derive(Debug, Clone, Deserialize)]
pub struct SearchResultItem {
    pub entity: Entity,
    pub score: f64,
    pub source: String,
    #[serde(rename = "contentPreview", default)]
    pub content_preview: Option<String>,
    #[serde(rename = "relatedEntities", default)]
    pub related_entities: Option<Vec<RelatedEntity>>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct SemanticSearchResponse {
    pub items: Vec<SearchResultItem>,
    pub total: u32,
    #[serde(rename = "nextOffset", default)]
    pub next_offset: Option<u32>,
}

// --- List Entity Events ---

#[derive(Debug, Clone, Serialize)]
pub struct ListEntityEventsRequest {
    #[serde(rename = "entityId")]
    pub entity_id: String,
    #[serde(rename = "eventTypes", skip_serializing_if = "Option::is_none")]
    pub event_types: Option<Vec<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<u32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub offset: Option<u32>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct EntityEvent {
    pub id: String,
    #[serde(rename = "entityId")]
    pub entity_id: String,
    #[serde(rename = "eventType")]
    pub event_type: String,
    #[serde(rename = "snapshotKey", default)]
    pub snapshot_key: Option<String>,
    #[serde(rename = "actorId")]
    pub actor_id: String,
    pub operation: String,
    #[serde(default)]
    pub metadata: Option<HashMap<String, serde_json::Value>>,
    #[serde(rename = "createdAt")]
    pub created_at: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListEntityEventsResponse {
    pub events: Vec<EntityEvent>,
    pub total: u32,
}

// --- Metrics ---

#[derive(Debug, Clone, Serialize)]
pub struct MetricsRequest {
    pub scope: String,
    #[serde(rename = "tenantId", skip_serializing_if = "Option::is_none")]
    pub tenant_id: Option<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct MetricsData {
    #[serde(rename = "requestsPerSecond")]
    pub requests_per_second: f64,
    #[serde(rename = "errorRate")]
    pub error_rate: f64,
    #[serde(rename = "latencyMsP50")]
    pub latency_ms_p50: f64,
    #[serde(rename = "latencyMsP95")]
    pub latency_ms_p95: f64,
    #[serde(rename = "latencyMsP99")]
    pub latency_ms_p99: f64,
}

#[derive(Debug, Clone, Deserialize)]
pub struct MetricsResponse {
    pub timestamp: String,
    pub metrics: MetricsData,
}

// --- IAM: Organizations ---

#[derive(Debug, Clone, Serialize)]
pub struct CreateOrgRequest {
    pub name: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct CreateOrgResponse {
    pub id: String,
    pub name: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct GetOrgRequest {
    #[serde(rename = "orgId")]
    pub org_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct GetOrgResponse {
    pub id: String,
    pub name: String,
    #[serde(rename = "createdAt")]
    pub created_at: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct UpdateOrgRequest {
    #[serde(rename = "orgId")]
    pub org_id: String,
    pub name: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct UpdateOrgResponse {
    pub id: String,
    pub name: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct DeleteOrgRequest {
    #[serde(rename = "orgId")]
    pub org_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct DeleteOrgResponse {
    #[serde(rename = "orgId")]
    pub org_id: String,
}

#[derive(Debug, Clone, Serialize, Default)]
pub struct ListOrgsRequest {}

#[derive(Debug, Clone, Deserialize)]
pub struct ListOrgsResponseItem {
    pub id: String,
    pub name: String,
    #[serde(rename = "createdAt")]
    pub created_at: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListOrgsResponse {
    pub orgs: Vec<ListOrgsResponseItem>,
    pub total: u32,
}

// --- IAM: Users ---

#[derive(Debug, Clone, Serialize)]
pub struct CreateUserRequest {
    pub username: String,
    pub password: String,
    #[serde(rename = "orgId")]
    pub org_id: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub role: Option<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct CreateUserResponse {
    pub id: String,
    pub username: String,
    #[serde(rename = "orgId")]
    pub org_id: String,
    pub role: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct GetUserRequest {
    #[serde(rename = "userId")]
    pub user_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct GetUserResponse {
    pub id: String,
    pub username: String,
    #[serde(rename = "orgId")]
    pub org_id: String,
    pub role: String,
    #[serde(rename = "platformRole", default)]
    pub platform_role: Option<String>,
    #[serde(rename = "createdAt")]
    pub created_at: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct UpdateUserRequest {
    #[serde(rename = "userId")]
    pub user_id: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub role: Option<String>,
    #[serde(rename = "platformRole", skip_serializing_if = "Option::is_none")]
    pub platform_role: Option<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct UpdateUserResponse {
    pub id: String,
    pub role: String,
    #[serde(rename = "platformRole", default)]
    pub platform_role: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct DeleteUserRequest {
    #[serde(rename = "userId")]
    pub user_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct DeleteUserResponse {
    #[serde(rename = "userId")]
    pub user_id: String,
}

#[derive(Debug, Clone, Serialize, Default)]
pub struct ListUsersRequest {
    #[serde(rename = "orgId", skip_serializing_if = "Option::is_none")]
    pub org_id: Option<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListUsersResponseItem {
    pub id: String,
    pub username: String,
    #[serde(rename = "orgId")]
    pub org_id: String,
    pub role: String,
    #[serde(rename = "platformRole", default)]
    pub platform_role: Option<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListUsersResponse {
    pub users: Vec<ListUsersResponseItem>,
    pub total: u32,
}

// --- IAM: Teams ---

#[derive(Debug, Clone, Serialize)]
pub struct CreateTeamRequest {
    pub name: String,
    #[serde(rename = "orgId", skip_serializing_if = "Option::is_none")]
    pub org_id: Option<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct CreateTeamResponse {
    pub id: String,
    pub name: String,
    #[serde(rename = "orgId")]
    pub org_id: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct GetTeamRequest {
    #[serde(rename = "teamId")]
    pub team_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct GetTeamResponse {
    pub id: String,
    pub name: String,
    #[serde(rename = "orgId")]
    pub org_id: String,
    #[serde(rename = "createdAt")]
    pub created_at: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct UpdateTeamRequest {
    #[serde(rename = "teamId")]
    pub team_id: String,
    pub name: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct UpdateTeamResponse {
    pub id: String,
    pub name: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct DeleteTeamRequest {
    #[serde(rename = "teamId")]
    pub team_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct DeleteTeamResponse {
    #[serde(rename = "teamId")]
    pub team_id: String,
}

#[derive(Debug, Clone, Serialize, Default)]
pub struct ListTeamsRequest {
    #[serde(rename = "orgId", skip_serializing_if = "Option::is_none")]
    pub org_id: Option<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListTeamsResponseItem {
    pub id: String,
    pub name: String,
    #[serde(rename = "orgId")]
    pub org_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListTeamsResponse {
    pub teams: Vec<ListTeamsResponseItem>,
    pub total: u32,
}

// --- IAM: Team Members ---

#[derive(Debug, Clone, Serialize)]
pub struct AddTeamMemberRequest {
    #[serde(rename = "teamId")]
    pub team_id: String,
    #[serde(rename = "userId")]
    pub user_id: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub role: Option<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct AddTeamMemberResponse {
    #[serde(rename = "teamId")]
    pub team_id: String,
    #[serde(rename = "userId")]
    pub user_id: String,
    pub role: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct RemoveTeamMemberRequest {
    #[serde(rename = "teamId")]
    pub team_id: String,
    #[serde(rename = "userId")]
    pub user_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct RemoveTeamMemberResponse {
    #[serde(rename = "teamId")]
    pub team_id: String,
    #[serde(rename = "userId")]
    pub user_id: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct ListTeamMembersRequest {
    #[serde(rename = "teamId")]
    pub team_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListTeamMembersResponseItem {
    #[serde(rename = "userId")]
    pub user_id: String,
    pub username: String,
    pub role: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListTeamMembersResponse {
    #[serde(rename = "teamId")]
    pub team_id: String,
    pub members: Vec<ListTeamMembersResponseItem>,
    pub total: u32,
}

// --- IAM: Entity Permissions ---

#[derive(Debug, Clone, Serialize)]
pub struct GrantPermissionRequest {
    #[serde(rename = "entityId")]
    pub entity_id: String,
    #[serde(rename = "granteeType")]
    pub grantee_type: String,
    #[serde(rename = "granteeId")]
    pub grantee_id: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub permission: Option<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct GrantPermissionResponse {
    #[serde(rename = "entityId")]
    pub entity_id: String,
    #[serde(rename = "granteeType")]
    pub grantee_type: String,
    #[serde(rename = "granteeId")]
    pub grantee_id: String,
    pub permission: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct RevokePermissionRequest {
    #[serde(rename = "entityId")]
    pub entity_id: String,
    #[serde(rename = "granteeType")]
    pub grantee_type: String,
    #[serde(rename = "granteeId")]
    pub grantee_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct RevokePermissionResponse {
    #[serde(rename = "entityId")]
    pub entity_id: String,
    #[serde(rename = "granteeType")]
    pub grantee_type: String,
    #[serde(rename = "granteeId")]
    pub grantee_id: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct ListPermissionsRequest {
    #[serde(rename = "entityId")]
    pub entity_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListPermissionsResponseItem {
    #[serde(rename = "granteeType")]
    pub grantee_type: String,
    #[serde(rename = "granteeId")]
    pub grantee_id: String,
    pub permission: String,
    #[serde(rename = "grantedBy")]
    pub granted_by: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListPermissionsResponse {
    #[serde(rename = "entityId")]
    pub entity_id: String,
    pub permissions: Vec<ListPermissionsResponseItem>,
    pub total: u32,
}

// --- Categories ---

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Category {
    pub id: String,
    pub name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(rename = "orgId")]
    pub org_id: String,
    #[serde(rename = "parentId", skip_serializing_if = "Option::is_none")]
    pub parent_id: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub children: Option<Vec<Category>>,
    #[serde(rename = "createdAt", skip_serializing_if = "Option::is_none")]
    pub created_at: Option<String>,
    #[serde(rename = "updatedAt", skip_serializing_if = "Option::is_none")]
    pub updated_at: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct CreateCategoryRequest {
    pub name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(rename = "parentId", skip_serializing_if = "Option::is_none")]
    pub parent_id: Option<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct CreateCategoryResponse {
    pub id: String,
    pub name: String,
    #[serde(rename = "orgId")]
    pub org_id: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct GetCategoryRequest {
    #[serde(rename = "categoryId")]
    pub category_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct GetCategoryResponse {
    pub category: Category,
}

#[derive(Debug, Clone, Serialize)]
pub struct UpdateCategoryRequest {
    #[serde(rename = "categoryId")]
    pub category_id: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(rename = "parentId", skip_serializing_if = "Option::is_none")]
    pub parent_id: Option<String>,
    #[serde(rename = "clearParent", skip_serializing_if = "Option::is_none")]
    pub clear_parent: Option<bool>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct UpdateCategoryResponse {
    pub id: String,
    pub name: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct DeleteCategoryRequest {
    #[serde(rename = "categoryId")]
    pub category_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct DeleteCategoryResponse {
    #[serde(rename = "categoryId")]
    pub category_id: String,
}

#[derive(Debug, Clone, Serialize, Default)]
pub struct ListCategoriesRequest {
    #[serde(rename = "parentId", skip_serializing_if = "Option::is_none")]
    pub parent_id: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tree: Option<bool>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListCategoriesResponse {
    pub categories: Vec<Category>,
    pub total: u32,
}

#[derive(Debug, Clone, Serialize)]
pub struct AssignEntityCategoryRequest {
    #[serde(rename = "entityId")]
    pub entity_id: String,
    #[serde(rename = "categoryId")]
    pub category_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct AssignEntityCategoryResponse {
    #[serde(rename = "entityId")]
    pub entity_id: String,
    #[serde(rename = "categoryId")]
    pub category_id: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct UnassignEntityCategoryRequest {
    #[serde(rename = "entityId")]
    pub entity_id: String,
    #[serde(rename = "categoryId")]
    pub category_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct UnassignEntityCategoryResponse {
    #[serde(rename = "entityId")]
    pub entity_id: String,
    #[serde(rename = "categoryId")]
    pub category_id: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct ListEntityCategoriesRequest {
    #[serde(rename = "entityId")]
    pub entity_id: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct ListEntityCategoriesResponse {
    #[serde(rename = "entityId")]
    pub entity_id: String,
    pub categories: Vec<Category>,
    pub total: u32,
}

// =====================================================================
// EMBED_BATCH
// =====================================================================

#[derive(Debug, Clone, Serialize)]
pub struct EmbedBatchRequest {
    pub texts: Vec<String>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct EmbedBatchResponse {
    pub embeddings: Vec<Vec<f32>>,
    pub dimensions: u32,
    #[serde(default)]
    pub model: String,
    #[serde(default)]
    pub cached: u32,
}
