/**
 * Workspace Sync Types
 *
 * Defines the protocol messages and abstractions for two-way state sync
 * between web clients, gateway, and user containers.
 *
 * The workspace is a unified namespace that:
 * - Syncs transient state (chartState) between client and gateway
 * - Syncs persistent state (chartStore) between client, gateway, and container
 * - Provides triggers for path changes (future use)
 * - Is channel-agnostic (works with WebSocket, Telegram, Slack, etc.)
 */

import type { Operation as JsonPatchOp } from 'fast-json-patch';

// =============================================================================
// Protocol Messages
// =============================================================================

/**
 * Full state snapshot for a store.
 * Sent when client connects or when catchup patches are unavailable.
 */
export interface SnapshotMessage {
  type: 'snapshot';
  store: string;
  seq: number;
  state: unknown;
}

/**
 * Incremental patch for a store.
 * Uses JSON Patch (RFC 6902) format.
 */
export interface PatchMessage {
  type: 'patch';
  store: string;
  seq: number;
  patch: JsonPatchOp[];
}

/**
 * Client hello message with current sequence numbers.
 * Sent on connect to request catchup patches or snapshots.
 */
export interface HelloMessage {
  type: 'hello';
  seqs: Record<string, number>;
}

/** Messages from client to gateway */
export type InboundSyncMessage = HelloMessage | PatchMessage;

/** Messages from gateway to client */
export type OutboundSyncMessage = SnapshotMessage | PatchMessage;

// =============================================================================
// Store Configuration
// =============================================================================

/**
 * Configuration for a workspace store.
 */
export interface StoreConfig {
  /** Unique store name (e.g., 'chartState', 'chartStore') */
  name: string;

  /** If true, store is persisted to user container via MCP */
  persistent: boolean;

  /** Factory function returning initial state for new sessions */
  initialState: () => unknown;
}

/**
 * Default store configurations.
 * Additional stores can be registered at runtime.
 */
export const DEFAULT_STORES: StoreConfig[] = [
  {
    name: 'chartState',
    persistent: true,
    initialState: () => ({
      symbol: 'BTC/USDT.BINANCE',
      start_time: null,
      end_time: null,
      period: 900,
      selected_shapes: [],
    }),
  },
  {
    name: 'shapes',
    persistent: true,
    initialState: () => ({ shapes: {} }),
  },
  {
    name: 'indicators',
    persistent: true,
    initialState: () => ({}),
  },
  {
    name: 'indicator_types',
    persistent: true,
    initialState: () => ({ types: {} }),
  },
  {
    name: 'strategy_types',
    persistent: true,
    initialState: () => ({ types: {} }),
  },
  {
    name: 'research_types',
    persistent: true,
    initialState: () => ({ types: {} }),
  },
  {
    name: 'channelState',
    persistent: false,
    initialState: () => ({
      connected: {},
    }),
  },
];

// =============================================================================
// Channel Adapter Interface
// =============================================================================

/**
 * Capabilities that a channel may support.
 */
export interface ChannelCapabilities {
  /** Channel supports sync protocol (snapshot/patch messages) */
  supportsSync: boolean;

  /** Channel supports sending images */
  supportsImages: boolean;

  /** Channel supports markdown formatting */
  supportsMarkdown: boolean;

  /** Channel supports streaming responses */
  supportsStreaming: boolean;

  /** Channel supports TradingView chart embeds */
  supportsTradingViewEmbed: boolean;
}

/**
 * Image message for channel adapters.
 * Contains base64-encoded image data from MCP tools.
 */
export interface ImageMessage {
  /** Base64-encoded image data */
  data: string;

  /** MIME type (e.g., 'image/png', 'image/jpeg') */
  mimeType: string;

  /** Optional caption/description */
  caption?: string;
}

/**
 * Text message for channel adapters.
 */
export interface TextMessage {
  /** Text content */
  text: string;
}

/**
 * Adapter interface for communication channels.
 * Implemented by WebSocket handler, Telegram handler, etc.
 */
export interface ChannelAdapter {
  /** Send a full state snapshot to the client */
  sendSnapshot(msg: SnapshotMessage): void;

  /** Send an incremental patch to the client */
  sendPatch(msg: PatchMessage): void;

  /** Send a text message to the client */
  sendText(msg: TextMessage): void;

  /** Send a streaming text chunk to the client */
  sendChunk(content: string): void;

  /** Send an image to the client */
  sendImage(msg: ImageMessage): void;

  /** Notify client that a tool call is being executed */
  sendToolCall?(toolName: string, label?: string): void;

  /** Get channel capabilities */
  getCapabilities(): ChannelCapabilities;
}

// =============================================================================
// Path Triggers (Future Use)
// =============================================================================

/**
 * Trigger handler function type.
 * Called when a watched path changes.
 */
export type PathTriggerHandler = (
  oldValue: unknown,
  newValue: unknown,
  context: PathTriggerContext
) => void | Promise<void>;

/**
 * Context passed to trigger handlers.
 */
export interface PathTriggerContext {
  /** Store name where change occurred */
  store: string;

  /** Full path that changed (JSON pointer) */
  path: string;

  /** Current sequence number after change */
  seq: number;

  /** User ID for this workspace */
  userId: string;

  /** Session ID for this workspace */
  sessionId: string;
}

/**
 * Registered path trigger.
 */
export interface PathTrigger {
  /** JSON pointer path to watch (e.g., '/chartState/symbol') */
  path: string;

  /** Handler called when path changes */
  handler: PathTriggerHandler;
}

// =============================================================================
// Store State Types (for type-safe access)
// =============================================================================

/**
 * Chart state - transient, tracks current view.
 */
export interface ChartState {
  symbol: string;
  start_time: number | null; // unix timestamp
  end_time: number | null; // unix timestamp
  period: number; // OHLC period in seconds (e.g., 900 for 15 minutes)
  selected_shapes: string[]; // list of shape ID's
}

/**
 * Control point for shapes (drawings/annotations).
 */
export interface ControlPoint {
  time: number; // unix timestamp
  price: number;
  channel?: string;
}

/**
 * Shape (drawing/annotation) on TradingView chart.
 */
export interface Shape {
  id: string;
  type: string;
  points: ControlPoint[];
  color?: string;
  line_width?: number;
  line_style?: string;
  properties?: Record<string, any>;
  symbol?: string;
  created_at?: number;
  modified_at?: number;
  original_id?: string;
}

/**
 * Shapes store - persistent, stores TradingView drawings and annotations.
 */
export type ShapesStore = { shapes: Record<string, Shape> };

/**
 * Parameter schema entry for a custom indicator.
 */
export interface CustomIndicatorParam {
  type: 'int' | 'float' | 'bool' | 'string';
  default: any;
  description?: string;
  min?: number;
  max?: number;
}

/**
 * Per-series plot configuration for a custom indicator output column.
 * style maps to LineStudyPlotStyle: 0=Line, 1=Histogram, 3=Dots/Cross,
 * 4=Area, 5=Columns, 6=Circles, 9=StepLine.
 */
export interface PlotConfig {
  style: number;
  color?: string;
  linewidth?: number;
  visible?: boolean;
}

/**
 * Shaded region between two plots ("plot_plot") or two bands ("hline_hline").
 */
export interface FilledAreaConfig {
  id: string;
  type: 'plot_plot' | 'hline_hline';
  series1: string;
  series2: string;
  color?: string;
  opacity?: number;
}

/**
 * Horizontal reference line (e.g. RSI overbought/oversold level).
 * linestyle: 0=solid, 1=dotted, 2=dashed.
 */
export interface BandConfig {
  id: string;
  value: number;
  color?: string;
  linewidth?: number;
  linestyle?: number;
  visible?: boolean;
}

/**
 * Output column descriptor for a custom indicator.
 */
export interface CustomIndicatorColumn {
  name: string;
  display_name?: string;
  description?: string;
  plot?: PlotConfig;
}

/**
 * Metadata needed to auto-construct a TradingView custom study.
 * Populated by the indicator subagent when adding a custom_ indicator.
 */
export interface CustomIndicatorMetadata {
  display_name: string;
  parameters: Record<string, CustomIndicatorParam>;
  input_series: string[];
  output_columns: CustomIndicatorColumn[];
  pane: 'price' | 'separate';
  filled_areas?: FilledAreaConfig[];
  bands?: BandConfig[];
}

/**
 * Indicator instance on TradingView chart.
 */
export interface IndicatorInstance {
  id: string;
  pandas_ta_name: string;
  instance_name: string;
  parameters: Record<string, any>;
  tv_study_id?: string;
  tv_indicator_name?: string;
  tv_inputs?: Record<string, any>;
  visible: boolean;
  pane: string;
  symbol?: string;
  created_at?: number;
  modified_at?: number;
  original_id?: string;
  /** Populated for custom_ indicators; drives TV custom study auto-construction. */
  custom_metadata?: CustomIndicatorMetadata;
}

/**
 * Indicators store - persistent, stores TradingView studies/indicators.
 */
export type IndicatorsStore = Record<string, IndicatorInstance>;

/**
 * Channel state - transient, tracks connected channels.
 * NOTE: This store is gateway-only and should NOT be synced to web clients.
 */
export interface ChannelState {
  connected: Record<string, ChannelInfo>;
}

/**
 * Information about a connected channel.
 */
export interface ChannelInfo {
  type: string;
  connectedAt: number;
  capabilities: ChannelCapabilities;
}

/**
 * Map of store names to their state types.
 */
export interface WorkspaceStores {
  chartState: ChartState;
  shapes: ShapesStore;
  indicators: IndicatorsStore;
  channelState: ChannelState;
  [key: string]: unknown;
}
