import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  CreateDateColumn,
  ManyToOne,
  JoinColumn,
  Index,
  Check,
} from 'typeorm';

/**
 * Context types for AI interactions
 * Based on architecture.md#task_ai_contexts Collection
 */
export enum AIContextType {
  PROMPT = 'prompt',
  RESULT = 'result',
  FEEDBACK = 'feedback',
  ERROR = 'error',
  UPDATE = 'update',
}

/**
 * AI agent types supported by the system
 */
export enum AIAgentType {
  OPENAI = 'openai',
  LANGCHAIN = 'langchain',
  NLP = 'nlp',
  CLAUDE_CODE = 'claude_code',
  BMAD_AGENT = 'bmad_agent',
  CUSTOM = 'custom',
}

/**
 * Interface for context data JSON field
 */
export interface AIContextData {
  // For prompts
  prompt?: string;
  systemPrompt?: string;
  parameters?: Record<string, any>;
  
  // For results
  response?: string;
  completionTokens?: number;
  promptTokens?: number;
  totalTokens?: number;
  
  // For feedback
  feedbackType?: 'positive' | 'negative' | 'correction';
  feedbackMessage?: string;
  userRating?: number;
  
  // For errors
  errorCode?: string;
  errorMessage?: string;
  stackTrace?: string;
  retryCount?: number;
  
  // Common metadata
  modelUsed?: string;
  temperature?: number;
  maxTokens?: number;
  timestamp?: string;
  sessionId?: string;
  requestId?: string;
  
  // Additional flexible data
  metadata?: Record<string, any>;
}

/**
 * Entity for storing AI agent context and prompt data
 * Tracks all AI interactions for tasks including prompts, results, feedback, and errors
 * 
 * Based on architecture.md#task_ai_contexts Collection (lines 213-224)
 */
@Entity('task_ai_contexts')
@Index(['task_id', 'execution_timestamp']) // Composite index for task history queries
@Index(['ai_agent_type', 'context_type']) // Index for agent-specific queries
@Index(['execution_timestamp']) // Index for time-based queries
export class TaskAIContextEntity {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  /**
   * Foreign key to tasks.id
   * References the task this AI context belongs to
   */
  @Column({ type: 'uuid', name: 'task_id' })
  @Index()
  task_id: string;

  /**
   * Type of AI agent (openai, langchain, claude_code, bmad_agent, etc.)
   */
  @Column({
    type: 'varchar',
    length: 50,
    name: 'ai_agent_type',
  })
  ai_agent_type: AIAgentType;

  /**
   * Type of context (prompt, result, feedback, error)
   */
  @Column({
    type: 'varchar',
    length: 20,
    name: 'context_type',
  })
  context_type: AIContextType;

  /**
   * JSON data containing prompts, responses, metadata
   * Uses simple-json for SQLite compatibility
   */
  @Column({
    type: 'simple-json',
    name: 'context_data',
    nullable: true,
  })
  context_data: AIContextData;

  /**
   * Timestamp when the AI execution occurred
   */
  @Column({
    type: 'datetime',
    name: 'execution_timestamp',
  })
  execution_timestamp: Date;

  /**
   * Whether the AI operation was successful
   */
  @Column({
    type: 'boolean',
    default: true,
  })
  success: boolean;

  /**
   * Number of tokens used in the operation (nullable)
   */
  @Column({
    type: 'int',
    nullable: true,
    name: 'tokens_used',
  })
  tokens_used: number | null;

  /**
   * Execution time in milliseconds (nullable)
   */
  @Column({
    type: 'int',
    nullable: true,
    name: 'execution_time_ms',
  })
  execution_time_ms: number | null;

  /**
   * Timestamp when the record was created
   */
  @CreateDateColumn({
    name: 'created_at',
  })
  created_at: Date;

  // Helper methods

  /**
   * Calculate the cost based on token usage
   * @param pricePerToken Price per token in USD
   * @returns Estimated cost in USD
   */
  calculateCost(pricePerToken: number = 0.00002): number | null {
    if (!this.tokens_used) return null;
    return this.tokens_used * pricePerToken;
  }

  /**
   * Check if this is an error context
   */
  isError(): boolean {
    return this.context_type === AIContextType.ERROR || !this.success;
  }

  /**
   * Get the total token count from context data
   */
  getTotalTokens(): number {
    if (this.tokens_used) return this.tokens_used;
    if (this.context_data?.totalTokens) return this.context_data.totalTokens;
    const prompt = this.context_data?.promptTokens || 0;
    const completion = this.context_data?.completionTokens || 0;
    return prompt + completion;
  }

  /**
   * Get a summary of the context for logging
   */
  getSummary(): string {
    const tokens = this.getTotalTokens();
    const time = this.execution_time_ms ? `${this.execution_time_ms}ms` : 'N/A';
    const status = this.success ? '✅' : '❌';
    
    return `${status} ${this.ai_agent_type} ${this.context_type} - Tokens: ${tokens}, Time: ${time}`;
  }

  /**
   * Validate the entity before saving
   */
  validate(): void {
    if (!this.task_id) {
      throw new Error('task_id is required');
    }
    
    if (!this.ai_agent_type) {
      throw new Error('ai_agent_type is required');
    }
    
    if (!this.context_type) {
      throw new Error('context_type is required');
    }
    
    if (!this.execution_timestamp) {
      this.execution_timestamp = new Date();
    }
    
    // Validate token usage is non-negative
    if (this.tokens_used !== null && this.tokens_used < 0) {
      throw new Error('tokens_used must be non-negative');
    }
    
    // Validate execution time is non-negative
    if (this.execution_time_ms !== null && this.execution_time_ms < 0) {
      throw new Error('execution_time_ms must be non-negative');
    }
  }
}