// agent/custom_scripts/types.ts

/**
 * Email interface representing an email message
 */
export interface Email {
  messageId: string;
  from: string;
  to: string;
  subject: string;
  body: string;
  date: string;
  isRead: boolean;
  hasAttachments: boolean;
  labels?: string[];
  uid?: number;
}

/**
 * Types of events that listeners can subscribe to
 */
export type EventType =
  | "email_received"        // New email arrives
  | "email_sent"            // User sends an email
  | "email_starred"         // Email is starred
  | "email_archived"        // Email is archived
  | "email_labeled"         // Label added to email
  | "scheduled_time";       // Time-based (cron)

/**
 * Configuration for a listener
 */
export interface ListenerConfig {
  // Unique identifier for this listener
  id: string;

  // Human-readable name
  name: string;

  // Optional description of what this listener does
  description?: string;

  // Whether this listener is active
  enabled: boolean;

  // Type of event to listen for
  event: EventType;
}

/**
 * Options for notify context method
 */
export interface NotifyOptions {
  // Priority for notification display
  priority?: "low" | "normal" | "high";
}

/**
 * Options for calling a subagent
 */
export interface SubagentOptions<T = any> {
  // The prompt to send to the agent
  prompt: string;

  // JSON Schema for structured response
  schema: {
    type: "object";
    properties: Record<string, any>;
    required?: string[];
  };

  // Optional model to use (defaults to haiku for speed)
  model?: "opus" | "sonnet" | "haiku";
}

/**
 * Context object provided to listener handlers
 * Contains methods to interact with the email system and user
 */
export interface ListenerContext {
  // Show a notification to the user
  notify(message: string, options?: NotifyOptions): Promise<void>;

  // Email actions
  archiveEmail(emailId: string): Promise<void>;
  starEmail(emailId: string): Promise<void>;
  unstarEmail(emailId: string): Promise<void>;
  markAsRead(emailId: string): Promise<void>;
  markAsUnread(emailId: string): Promise<void>;
  addLabel(emailId: string, label: string): Promise<void>;
  removeLabel(emailId: string, label: string): Promise<void>;

  // Call a subagent with a prompt and get structured response
  callAgent<T = any>(options: SubagentOptions<T>): Promise<T>;

  // UI State operations
  uiState: {
    get<T>(stateId: string): Promise<T | null>;
    set<T>(stateId: string, data: T): Promise<void>;
  };
}

/**
 * Result returned by a listener handler to indicate what it did
 */
export interface ListenerResult {
  // Whether the listener performed any actions
  executed: boolean;

  // Human-readable reason explaining why the listener did or didn't execute
  // Examples: "Email from Bank of America - added Finance label"
  //          "Not a financial email - sender domain not recognized"
  reason: string;

  // Optional array of action descriptions
  // Examples: ["starred", "labeled:Finance", "archived"]
  actions?: string[];

  // Optional component instances to render
  components?: ComponentInstance[];
}

/**
 * A listener module exports a config and handler function
 */
export interface ListenerModule {
  config: ListenerConfig;
  handler: (data: any, context: ListenerContext) => Promise<ListenerResult | void>;
}

/**
 * Action Template Definition
 * Defines a reusable action pattern that can be instantiated with parameters
 */
export interface ActionTemplate {
  // Unique identifier for this action template
  id: string;

  // Human-readable name
  name: string;

  // Description of what this template does
  description: string;

  // Optional emoji or icon
  icon?: string;

  // JSON Schema defining required/optional parameters
  parameterSchema: {
    type: "object";
    properties: Record<string, {
      type: string;
      description: string;
      enum?: string[];
      default?: any;
    }>;
    required?: string[];
  };
}

/**
 * Action Instance
 * Created by agent during conversation by providing parameters to a template
 */
export interface ActionInstance {
  // Unique ID for this specific action instance
  instanceId: string;

  // Reference to template ID
  templateId: string;

  // Label shown on button (generated by agent)
  label: string;

  // Optional description (more context)
  description?: string;

  // Parameters to pass to handler
  params: Record<string, any>;

  // Button styling
  style?: "primary" | "secondary" | "danger";

  // Session ID this action belongs to
  sessionId: string;

  // Timestamp when created
  createdAt: string;
}

/**
 * Email search criteria
 */
export interface EmailSearchCriteria {
  from?: string;
  to?: string;
  subject?: string;
  hasAttachment?: boolean;
  isUnread?: boolean;
  labels?: string[];
  before?: Date;
  after?: Date;
}

/**
 * Action Context
 * Provides capabilities to action handlers (similar to ListenerContext)
 */
export interface ActionContext {
  // Session information
  sessionId: string;

  // Email API operations
  emailAPI: {
    getInbox(options?: { limit?: number; includeRead?: boolean }): Promise<Email[]>;
    searchEmails(criteria: EmailSearchCriteria): Promise<Email[]>;
    searchWithGmailQuery(query: string): Promise<Email[]>;
    getEmailsByIds(ids: string[]): Promise<Email[]>;
    getEmailById(id: string): Promise<Email | null>;
  };

  // Direct email operations (similar to listeners)
  archiveEmail(emailId: string): Promise<void>;
  starEmail(emailId: string): Promise<void>;
  unstarEmail(emailId: string): Promise<void>;
  markAsRead(emailId: string): Promise<void>;
  markAsUnread(emailId: string): Promise<void>;
  addLabel(emailId: string, label: string): Promise<void>;
  removeLabel(emailId: string, label: string): Promise<void>;

  // Send emails
  sendEmail(options: {
    to: string;
    subject: string;
    body: string;
    cc?: string;
    bcc?: string;
    replyTo?: string;
  }): Promise<{ messageId: string }>;

  // AI/Agent capabilities
  callAgent<T = any>(options: {
    prompt: string;
    systemPrompt?: string;
    tools?: string[];
    maxTokens?: number;
  }): Promise<T>;

  // Session messaging (inject messages into chat)
  addUserMessage(content: string): void;
  addAssistantMessage(content: string): void;
  addSystemMessage(content: string): void;

  // Notifications
  notify(message: string, options?: {
    priority?: "low" | "normal" | "high";
    type?: "info" | "success" | "warning" | "error";
  }): void;

  // External API access
  fetch(url: string, options?: RequestInit): Promise<Response>;

  // Logging
  log(message: string, level?: "info" | "warn" | "error"): void;

  // UI State operations
  uiState: {
    get<T>(stateId: string): Promise<T | null>;
    set<T>(stateId: string, data: T): Promise<void>;
  };
}

/**
 * Action Result
 * Returned by handler to indicate execution outcome
 */
export interface ActionResult {
  // Whether action succeeded
  success: boolean;

  // Human-readable message describing result
  message: string;

  // Optional structured data to return
  data?: Record<string, any>;

  // Optional array of follow-up actions to suggest
  suggestedActions?: ActionInstance[];

  // Whether to refresh inbox after this action
  refreshInbox?: boolean;

  // Optional component instances to render
  components?: ComponentInstance[];
}

/**
 * Action Log Entry
 * Stored in .logs/actions/ for audit trail
 */
export interface ActionLogEntry {
  timestamp: string;
  instanceId: string;
  templateId: string;
  sessionId: string;
  params: Record<string, any>;
  result: ActionResult;
  duration: number; // milliseconds
  error?: string;
}

// ============================================================================
// UI State and Components System
// ============================================================================

/**
 * UI State Template Definition
 * Defines a persistent state structure that can be updated by actions/listeners
 * and rendered by components
 */
export interface UIStateTemplate<T = any> {
  // Unique identifier for this state type
  id: string;

  // Human-readable name
  name: string;

  // Description of what this state represents
  description?: string;

  // Initial state structure when created
  initialState: T;
}

/**
 * Component Template Definition
 * Defines a UI component that renders a specific UI state
 */
export interface ComponentTemplate {
  // Unique identifier for this component
  id: string;

  // Human-readable name
  name: string;

  // Description of what this component displays
  description?: string;

  // Which UI state template this component uses
  stateId: string;
}

/**
 * Component Instance
 * Created when an action/listener wants to render a component
 */
export interface ComponentInstance {
  // Unique ID for this specific instance
  instanceId: string;

  // Reference to component template ID
  componentId: string;

  // Which UI state instance to bind to
  stateId: string;

  // Session ID this component belongs to
  sessionId?: string;

  // Timestamp when created
  createdAt?: string;
}

/**
 * Props passed to React components
 */
export interface ComponentProps<T = any> {
  // The current UI state data
  state: T;

  // Callback to trigger actions from the component
  onAction: (actionId: string, params: Record<string, any>) => void;
}

/**
 * Component Context
 * Available to component lifecycle hooks (if needed)
 */
export interface ComponentContext {
  // UI State operations
  uiState: {
    get<T>(stateId: string): Promise<T | null>;
    set<T>(stateId: string, data: T): Promise<void>;
  };

  // Trigger actions
  triggerAction(templateId: string, params: Record<string, any>): Promise<ActionResult>;

  // Notifications
  notify(message: string, type?: "info" | "success" | "warning" | "error"): void;

  // Logging
  log(message: string, data?: Record<string, any>): void;
}

/**
 * UI State Module
 * Exports a configuration from a UI state file
 */
export interface UIStateModule<T = any> {
  config: UIStateTemplate<T>;
}

/**
 * Component Module
 * Exports configuration and React component from a component file
 */
export interface ComponentModule {
  config: ComponentTemplate;
  Component: React.ComponentType<ComponentProps<any>>;
}
