// Types matching Go response structs

export interface SystemInfo {
  name: string;
  version: string;
  commit: string;
  build_date: string;
  description: string;
  transport: string;
  config_mode: string;
  portal_title: string;
  portal_logo: string;
  portal_logo_light: string;
  portal_logo_dark: string;
  features: SystemFeatures;
  toolkit_count: number;
  persona_count: number;
}

export interface SystemFeatures {
  audit: boolean;
  oauth: boolean;
  knowledge: boolean;
  admin: boolean;
  database: boolean;
}

export interface ToolInfo {
  name: string;
  title?: string;
  toolkit: string;
  kind: string;
  connection: string;
  /** True when the tool is excluded from tools/list by tools.allow / tools.deny. */
  hidden: boolean;
}

export interface ToolListResponse {
  tools: ToolInfo[];
  total: number;
}

export interface ConnectionInfo {
  kind: string;
  name: string;
  connection: string;
  tools: string[];
  hidden_tools: string[];
}

export interface ConnectionListResponse {
  connections: ConnectionInfo[];
  total: number;
}

// Matches Go audit.Event. Fields with omitempty in Go are optional here
// because the backend omits them when empty/nil.
export interface AuditEvent {
  id: string;
  timestamp: string;
  duration_ms: number;
  request_id: string;
  session_id: string;
  user_id: string;
  user_email?: string;
  persona?: string;
  tool_name: string;
  toolkit_kind?: string;
  toolkit_name?: string;
  connection?: string;
  parameters?: Record<string, unknown>;
  success: boolean;
  error_message?: string;
  response_chars: number;
  request_chars: number;
  content_blocks: number;
  transport: string;
  source: string;
  enrichment_applied: boolean;
  authorized: boolean;
}

export interface AuditEventResponse {
  data: AuditEvent[];
  total: number;
  page: number;
  per_page: number;
}

export interface TimeseriesBucket {
  bucket: string;
  count: number;
  success_count: number;
  error_count: number;
  avg_duration_ms: number;
}

export interface BreakdownEntry {
  dimension: string;
  count: number;
  success_rate: number;
  avg_duration_ms: number;
}

export interface Overview {
  total_calls: number;
  success_rate: number;
  avg_duration_ms: number;
  unique_users: number;
  unique_tools: number;
  enrichment_rate: number;
  error_count: number;
}

export interface PerformanceStats {
  p50_ms: number;
  p95_ms: number;
  p99_ms: number;
  avg_ms: number;
  max_ms: number;
  avg_response_chars: number;
  avg_request_chars: number;
}

export type Resolution = "minute" | "hour" | "day";
export type BreakdownDimension =
  | "tool_name"
  | "user_id"
  | "persona"
  | "toolkit_kind"
  | "connection";

export interface AuditStatsResponse {
  total: number;
  success: number;
  failures: number;
}

export interface AuditFiltersResponse {
  users: string[];
  tools: string[];
  toolkit_kinds: string[];
  sources: string[];
  user_labels?: Record<string, string>;
}

export type AuditSortColumn =
  | "timestamp"
  | "user_id"
  | "tool_name"
  | "toolkit_kind"
  | "source"
  | "connection"
  | "duration_ms"
  | "success"
  | "enrichment_applied";

export type SortOrder = "asc" | "desc";

// ---------------------------------------------------------------------------
// Knowledge — Insights & Changesets
// ---------------------------------------------------------------------------

export interface SuggestedAction {
  action_type: string;
  target: string;
  detail: string;
}

export interface RelatedColumn {
  urn: string;
  column: string;
  relevance: string;
}

export interface Insight {
  id: string;
  created_at: string;
  session_id: string;
  captured_by: string;
  persona: string;
  category: string;
  insight_text: string;
  confidence: string;
  entity_urns: string[];
  related_columns: RelatedColumn[];
  suggested_actions: SuggestedAction[];
  status: string;
  reviewed_by?: string;
  reviewed_at?: string;
  review_notes?: string;
  applied_by?: string;
  applied_at?: string;
  changeset_ref?: string;
}

export interface InsightListResponse {
  data: Insight[];
  total: number;
  page: number;
  per_page: number;
}

export interface EntityInsightSummary {
  entity_urn: string;
  count: number;
  categories: string[];
  latest_at: string;
}

export interface InsightStats {
  total_pending: number;
  by_entity: EntityInsightSummary[];
  by_category: Record<string, number>;
  by_confidence: Record<string, number>;
  by_status: Record<string, number>;
}

export interface Changeset {
  id: string;
  created_at: string;
  target_urn: string;
  change_type: string;
  previous_value: Record<string, unknown>;
  new_value: Record<string, unknown>;
  source_insight_ids: string[];
  approved_by: string;
  applied_by: string;
  rolled_back: boolean;
  rolled_back_by?: string;
  rolled_back_at?: string;
}

export interface ChangesetListResponse {
  data: Changeset[];
  total: number;
  page: number;
  per_page: number;
}

export type InsightCategory =
  | "correction"
  | "business_context"
  | "data_quality"
  | "usage_guidance"
  | "relationship"
  | "enhancement";

export type InsightConfidence = "high" | "medium" | "low";

export type InsightStatus =
  | "pending"
  | "approved"
  | "rejected"
  | "applied"
  | "superseded"
  | "rolled_back";

// ---------------------------------------------------------------------------
// Tools — Schema & Execution
// ---------------------------------------------------------------------------

/** JSON Schema property for a single tool parameter. */
export interface ToolParameterSchema {
  type: "string" | "integer" | "boolean";
  description: string;
  format?: "sql" | "urn";
  enum?: string[];
  default?: string | number | boolean;
}

/** Full schema for a tool including input parameters. */
export interface ToolSchema {
  name: string;
  title?: string;
  kind: string;
  description: string;
  parameters: {
    type: "object";
    required: string[];
    properties: Record<string, ToolParameterSchema>;
  };
}

/** Batch response from GET /tools/schemas. */
export interface ToolSchemaMap {
  schemas: Record<string, ToolSchema>;
}

/** Request body for POST /tools/call. */
export interface ToolCallRequest {
  tool_name: string;
  connection: string;
  parameters: Record<string, unknown>;
}

/** A content block in the MCP response. */
export interface ToolContentBlock {
  type: "text";
  text: string;
}

/** Response from POST /tools/call. Mirrors MCP CallToolResult. */
export interface ToolCallResponse {
  content: ToolContentBlock[];
  is_error: boolean;
  duration_ms: number;
}

// ---------------------------------------------------------------------------
// Personas
// ---------------------------------------------------------------------------

export interface PersonaContextOverrides {
  description_prefix?: string;
  description_override?: string;
  agent_instructions_suffix?: string;
  agent_instructions_override?: string;
}

export interface PersonaSummary {
  name: string;
  display_name: string;
  description?: string;
  roles: string[];
  tool_count: number;
  source?: "file" | "database" | "both";
}

export interface PersonaDetail {
  name: string;
  display_name: string;
  description?: string;
  roles: string[];
  priority: number;
  allow_tools: string[];
  deny_tools: string[];
  allow_connections?: string[];
  deny_connections?: string[];
  tools: string[];
  context?: PersonaContextOverrides;
  source?: "file" | "database" | "both";
}

export interface PersonaListResponse {
  personas: PersonaSummary[];
  total: number;
}

export interface PersonaCreateRequest {
  name: string;
  display_name: string;
  description?: string;
  roles: string[];
  allow_tools: string[];
  deny_tools?: string[];
  allow_connections?: string[];
  deny_connections?: string[];
  priority?: number;
  description_prefix?: string;
  description_override?: string;
  agent_instructions_suffix?: string;
  agent_instructions_override?: string;
}

// ---------------------------------------------------------------------------
// Assets (admin-scoped)
// ---------------------------------------------------------------------------

export { type Asset, type ShareSummary } from "@/api/portal/types";

export interface AdminAssetListResponse {
  data: import("@/api/portal/types").Asset[];
  total: number;
  limit: number;
  offset: number;
  share_summaries?: Record<string, import("@/api/portal/types").ShareSummary>;
}


// ---------------------------------------------------------------------------
// API Keys
// ---------------------------------------------------------------------------

export interface APIKeySummary {
  name: string;
  email?: string;
  description?: string;
  roles: string[];
  expires_at?: string;
  expired?: boolean;
  source?: "file" | "database" | "both";
}

export interface APIKeyListResponse {
  keys: APIKeySummary[];
  total: number;
}

export interface APIKeyCreateResponse {
  name: string;
  email?: string;
  description?: string;
  key: string;
  roles: string[];
  expires_at?: string;
  warning: string;
}

// --- Config entries ---

export interface ConfigEntry {
  key: string;
  value: string;
  updated_by: string;
  updated_at: string;
}

export interface ConfigChangelogEntry {
  id: number;
  key: string;
  action: string;
  value?: string;
  changed_by: string;
  changed_at: string;
}

export interface EffectiveConfigEntry {
  key: string;
  value: string;
  source: "file" | "database";
  updated_by?: string;
  updated_at?: string;
}

// ---------------------------------------------------------------------------
// Connection Instances (DB-managed)
// ---------------------------------------------------------------------------

export interface ConnectionInstance {
  kind: string;
  name: string;
  config: Record<string, any>;
  description: string;
  created_by: string;
  updated_at: string;
}

// ---------------------------------------------------------------------------
// Prompts
// ---------------------------------------------------------------------------

export interface PromptArgument {
  name: string;
  description: string;
  required: boolean;
}

export interface Prompt {
  id: string;
  name: string;
  display_name: string;
  description: string;
  content: string;
  arguments: PromptArgument[];
  category: string;
  scope: "global" | "persona" | "personal" | "system";
  personas: string[];
  owner_email: string;
  source: string;
  enabled: boolean;
  created_at: string;
  updated_at: string;
}

export interface PromptListResponse {
  data: Prompt[];
  total: number;
}

export interface EffectiveConnection {
  kind: string;
  name: string;
  connection: string;
  description?: string;
  source: "file" | "database" | "both";
  tools: string[];
  config?: Record<string, any>;
  created_by?: string;
  updated_at?: string;
}

// ---------------------------------------------------------------------------
// Gateway (third-party MCP proxy)
// ---------------------------------------------------------------------------

export interface GatewayProbeTool {
  name: string;
  local_name: string;
  description?: string;
}

export interface GatewayTestResponse {
  healthy: boolean;
  tools?: GatewayProbeTool[];
  error?: string;
}

export interface GatewayRefreshResponse {
  healthy: boolean;
  tools?: string[];
  error?: string;
}

export interface GatewayOAuthStatus {
  configured: boolean;
  token_acquired: boolean;
  expires_at?: string;
  last_refreshed_at?: string;
  has_refresh_token: boolean;
  refresh_expires_at?: string;
  last_error?: string;
  grant?: string;
  token_url?: string;
  scope?: string;
  authenticated_by?: string;
  authenticated_at?: string;
  needs_reauth?: boolean;
  refresh_token_revoked?: boolean;
}

export interface GatewayOAuthStartResponse {
  authorization_url: string;
  state: string;
  redirect_uri: string;
  expires_at: string;
}

// ConnectionOAuthStatus mirrors connoauth.OAuthStatus from the backend.
// Returned by the unified /connections/{kind}/{name}/oauth-status
// endpoint for any connection kind. Distinct from GatewayOAuthStatus
// only because the backend type lives in a different package; the
// fields are intentionally a superset for portal compatibility.
// ConnectionOAuthHealthSummary is one row of the bulk
// /connections/oauth-health endpoint. Powers the connection-list
// health badge.
//
// has_oauth=false means the connection is not OAuth-configured at
// all (bearer / api_key / none); the UI hides the badge for those.
//
// idp_error_code is the RFC 6749 `error` field from the latest
// refresh_failed_* event, empty when the last refresh succeeded or
// no events exist. Drives the tooltip text so the operator sees
// "invalid_client" or "invalid_grant" without navigating away from
// the connection list.
export interface ConnectionOAuthHealthSummary {
  kind: string;
  name: string;
  has_oauth: boolean;
  needs_reauth: boolean;
  token_acquired: boolean;
  idp_error_code?: string;
}

export interface ConnectionsOAuthHealthResponse {
  connections: ConnectionOAuthHealthSummary[];
}

export interface ConnectionOAuthStatus {
  configured: boolean;
  token_acquired: boolean;
  expires_at?: string;
  last_refreshed_at?: string;
  has_refresh_token: boolean;
  refresh_expires_at?: string;
  last_error?: string;
  token_url?: string;
  scope?: string;
  authenticated_by?: string;
  authenticated_at?: string;
  needs_reauth?: boolean;
  last_revocation?: {
    occurred_at: string;
    reason?: string;
    idp_host?: string;
  };
}

// ConnectionAuthEvent mirrors authevents.Event. The History panel
// renders the most recent N of these for the active connection.
export interface ConnectionAuthEvent {
  id: string;
  occurred_at: string;
  connection_kind?: string;
  connection_name?: string;
  event_type:
    | "connect_started"
    | "connect_completed"
    | "refresh_succeeded"
    | "refresh_failed_transient"
    | "refresh_failed_revoked"
    | "refresh_skipped_no_token"
    | "refresh_skipped_expired"
    | "refresh_rotation_persistence_failed"
    | "token_deleted_revoked"
    | "token_deleted_admin";
  actor: string;
  idp_host?: string;
  detail?: Record<string, unknown>;
}

export interface GatewayConnectionStatus {
  name: string;
  healthy: boolean;
  auth_mode: string;
  tools?: string[];
  oauth?: GatewayOAuthStatus;
}

export interface EnrichmentPredicate {
  kind?: "" | "always" | "response_contains";
  paths?: string[];
}

export interface EnrichmentAction {
  source: string;
  operation: string;
  parameters?: Record<string, any>;
}

export interface EnrichmentMerge {
  kind?: "" | "path";
  path?: string;
}

export interface EnrichmentRule {
  id: string;
  connection_name: string;
  tool_name: string;
  when_predicate: EnrichmentPredicate;
  enrich_action: EnrichmentAction;
  merge_strategy: EnrichmentMerge;
  description?: string;
  enabled: boolean;
  created_by?: string;
  created_at: string;
  updated_at: string;
}

export interface EnrichmentRuleBody {
  tool_name: string;
  when_predicate: EnrichmentPredicate;
  enrich_action: EnrichmentAction;
  merge_strategy: EnrichmentMerge;
  description?: string;
  enabled: boolean;
}

export interface FiredRule {
  rule_id: string;
  source: string;
  op: string;
  skipped?: boolean;
  error?: string;
  duration_ms: number;
}

export interface DryRunRequest {
  args?: Record<string, any>;
  response?: any;
  user?: { id?: string; email?: string };
}

export interface DryRunResponse {
  response: any;
  warnings?: string[];
  fired?: FiredRule[];
}

// ---------------------------------------------------------------------------
// Memory
// ---------------------------------------------------------------------------

export interface MemoryRecord {
  id: string;
  created_at: string;
  updated_at: string;
  created_by: string;
  persona: string;
  dimension: string;
  content: string;
  category: string;
  confidence: string;
  source: string;
  entity_urns: string[];
  related_columns: RelatedColumn[];
  metadata: Record<string, unknown>;
  status: string;
  stale_reason?: string;
  stale_at?: string;
  last_verified?: string;
}

export interface MemoryListResponse {
  data: MemoryRecord[];
  total: number;
  page: number;
  per_page: number;
}

export interface MemoryStats {
  total: number;
  by_dimension: Record<string, number>;
  by_category: Record<string, number>;
  by_status: Record<string, number>;
}

// --- Tools master-detail (issue #340) ---

export type PersonaAccessSource = "allow" | "deny" | "default";

export interface ToolPersonaAccess {
  persona: string;
  /** End-to-end: tool rule allows AND connection rule allows. */
  allowed: boolean;
  matched_pattern?: string;
  /** Source of the tool-rule decision (not the connection check). */
  source: PersonaAccessSource;
  /** Independent: whether this persona allows the tool's connection. */
  connection_allowed: boolean;
}

export interface ToolActivityAggregate {
  window_seconds: number;
  call_count: number;
  success_rate: number;
  avg_duration_ms: number;
}

export interface ToolDetail {
  name: string;
  title?: string;
  description: string;
  toolkit_kind: string;
  toolkit_name?: string;
  connection?: string;
  input_schema?: unknown;
  personas: ToolPersonaAccess[];
  hidden_by_global_deny: boolean;
  global_deny_pattern?: string;
  hidden_by_persona?: Record<string, boolean>;
  description_overridden: boolean;
  override_author?: string;
  activity?: ToolActivityAggregate;
  enrichment_rule_count: number;
}

export interface PersonaTestAccessRequest {
  tool_name: string;
}

export interface PersonaTestAccessResult {
  allowed: boolean;
  matched_pattern: string;
  source: PersonaAccessSource;
}

export interface ToolVisibilityRequest {
  hidden: boolean;
}

export interface ToolVisibilityResponse {
  tool_name: string;
  hidden: boolean;
  deny: string[];
}
