/**
 * AI Triage Service
 * Handles AI-powered classification for ambiguous tickets and text enhancement.
 * Only called when robotic classifier can't confidently classify, or when
 * title/description cleanup is needed.
 */

import { postgresClient } from './postgres-client';
import {
  AiEnhancementResult,
  AiPromptTemplate,
  TicketData,
  WorkflowSettings,
  ClassificationResult,
  PromptPurpose,
} from '../types/workflow';

export class AiTriageService {
  /**
   * Call the configured AI provider with a prompt.
   */
  private async callProvider(
    systemPrompt: string,
    userPrompt: string,
    settings: WorkflowSettings,
    templateOverrides?: { provider?: string; model?: string; temperature?: number; max_tokens?: number }
  ): Promise<string> {
    const provider = templateOverrides?.provider || settings.default_ai_provider;
    const temperature = templateOverrides?.temperature ?? 0.3;
    const maxTokens = templateOverrides?.max_tokens ?? 4000;

    if (provider === 'anthropic') {
      return this.callAnthropic(
        systemPrompt,
        userPrompt,
        templateOverrides?.model || settings.anthropic_model,
        settings.anthropic_api_key,
        temperature,
        maxTokens
      );
    } else {
      return this.callOpenAI(
        systemPrompt,
        userPrompt,
        templateOverrides?.model || settings.openai_model,
        settings.openai_api_key,
        temperature,
        maxTokens
      );
    }
  }

  /**
   * Call OpenAI API.
   */
  private async callOpenAI(
    systemPrompt: string,
    userPrompt: string,
    model: string,
    apiKey: string,
    temperature: number,
    maxTokens: number
  ): Promise<string> {
    if (!apiKey) throw new Error('OpenAI API key not configured');

    const response = await fetch('https://api.openai.com/v1/chat/completions', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${apiKey}`,
      },
      body: JSON.stringify({
        model,
        messages: [
          { role: 'system', content: systemPrompt },
          { role: 'user', content: userPrompt },
        ],
        temperature,
        max_tokens: maxTokens,
        response_format: { type: 'json_object' },
      }),
    });

    if (!response.ok) {
      const error = await response.text();
      throw new Error(`OpenAI API error (${response.status}): ${error}`);
    }

    const data = await response.json();
    return data.choices[0]?.message?.content || '';
  }

  /**
   * Call Anthropic API.
   */
  private async callAnthropic(
    systemPrompt: string,
    userPrompt: string,
    model: string,
    apiKey: string,
    temperature: number,
    maxTokens: number
  ): Promise<string> {
    if (!apiKey) throw new Error('Anthropic API key not configured');

    const response = await fetch('https://api.anthropic.com/v1/messages', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': apiKey,
        'anthropic-version': '2023-06-01',
      },
      body: JSON.stringify({
        model,
        max_tokens: maxTokens,
        temperature,
        system: systemPrompt,
        messages: [{ role: 'user', content: userPrompt }],
      }),
    });

    if (!response.ok) {
      const error = await response.text();
      throw new Error(`Anthropic API error (${response.status}): ${error}`);
    }

    const data = await response.json();
    const textBlock = data.content?.find((b: any) => b.type === 'text');
    return textBlock?.text || '';
  }

  /**
   * Load an active AI prompt template by purpose.
   */
  async getTemplate(purpose: PromptPurpose): Promise<AiPromptTemplate | null> {
    const result = await postgresClient.query<AiPromptTemplate>(
      `SELECT * FROM ai_prompt_templates WHERE purpose = $1 AND is_active = true ORDER BY version DESC LIMIT 1`,
      [purpose]
    );
    return result.rows[0] || null;
  }

  /**
   * Interpolate template variables in a prompt string.
   * Supports {{field}} syntax.
   */
  private interpolate(template: string, vars: Record<string, any>): string {
    return template.replace(/\{\{(\w+)\}\}/g, (_, key) => {
      const val = vars[key];
      return val !== undefined && val !== null ? String(val) : '';
    });
  }

  /**
   * Classify ambiguous fields that the robotic classifier couldn't handle.
   * Returns only the fields that AI classified.
   */
  async classifyAmbiguous(
    ticket: TicketData,
    failedFields: string[],
    settings: WorkflowSettings
  ): Promise<AiEnhancementResult> {
    const template = await this.getTemplate('ambiguous_classification');

    // Load picklist data for AI context
    const [issueTypes, subIssueTypes, priorities] = await Promise.all([
      postgresClient.query(`SELECT value, label FROM issue_types WHERE is_deleted = false ORDER BY label`),
      postgresClient.query(`SELECT value, label, parent_value FROM sub_issue_types WHERE is_deleted = false ORDER BY label`),
      postgresClient.query(`SELECT value, label FROM priorities WHERE is_active = true ORDER BY value`),
    ]);

    const picklistContext = {
      issueTypes: JSON.stringify(issueTypes.rows),
      subIssueTypes: JSON.stringify(subIssueTypes.rows),
      priorities: JSON.stringify(priorities.rows),
    };

    const systemPrompt = template?.system_prompt || this.getDefaultClassificationSystemPrompt();
    const userTemplate = template?.user_prompt_template || this.getDefaultClassificationUserPrompt();

    const userPrompt = this.interpolate(userTemplate, {
      title: ticket.title,
      description: ticket.description || 'No description provided',
      ticket_category: ticket.ticket_category,
      failed_fields: failedFields.join(', '),
      ...picklistContext,
    });

    const aiResponse = await this.callProvider(systemPrompt, userPrompt, settings, {
      provider: template?.provider,
      model: template?.model,
      temperature: template?.temperature,
      max_tokens: template?.max_tokens,
    });

    try {
      const parsed = JSON.parse(aiResponse);
      return {
        classification: {
          issue_type: parsed.issueType || parsed.issue_type,
          sub_issue_type: parsed.subIssueType || parsed.sub_issue_type,
          ticket_type: parsed.ticketType || parsed.ticket_type,
          priority: parsed.priority,
        },
        method: 'ai',
      };
    } catch {
      console.error('[AI-TRIAGE] Failed to parse AI classification response:', aiResponse);
      return { method: 'ai' };
    }
  }

  /**
   * Clean up a messy ticket title (email subject, too long, garbled).
   */
  async cleanupTitle(
    ticket: TicketData,
    settings: WorkflowSettings
  ): Promise<string | undefined> {
    if (!settings.ai_for_title_cleanup) return undefined;

    const template = await this.getTemplate('title_cleanup');
    const systemPrompt = template?.system_prompt ||
      'You are a helpdesk ticket title cleaner. Given a ticket title, produce a clean, concise title (max 80 chars). Remove email prefixes (Re:, Fw:, Fwd:), ticket numbers, excessive punctuation, and redundant info. Return JSON: {"title": "cleaned title"}';

    const userTemplate = template?.user_prompt_template ||
      'Clean up this ticket title:\n\nOriginal title: {{title}}\nDescription (for context): {{description}}';

    const userPrompt = this.interpolate(userTemplate, {
      title: ticket.title,
      description: (ticket.description || '').substring(0, 500),
    });

    const aiResponse = await this.callProvider(systemPrompt, userPrompt, settings, {
      provider: template?.provider,
      model: template?.model,
      temperature: template?.temperature ?? 0.2,
      max_tokens: template?.max_tokens ?? 200,
    });

    try {
      const parsed = JSON.parse(aiResponse);
      return parsed.title || undefined;
    } catch {
      console.error('[AI-TRIAGE] Failed to parse title cleanup response:', aiResponse);
      return undefined;
    }
  }

  /**
   * Rewrite/restructure a ticket description.
   */
  async rewriteDescription(
    ticket: TicketData,
    branch: string,
    settings: WorkflowSettings
  ): Promise<string | undefined> {
    if (!settings.ai_for_description_rewrite) return undefined;
    if (!ticket.description || ticket.description.length < 50) return undefined;

    const purpose: PromptPurpose = branch === 'noc' ? 'noc_format' : 'description_rewrite';
    const template = await this.getTemplate(purpose);
    if (!template) return undefined;

    const userPrompt = this.interpolate(template.user_prompt_template, {
      title: ticket.title,
      description: ticket.description,
      branch,
    });

    const aiResponse = await this.callProvider(template.system_prompt, userPrompt, settings, {
      provider: template.provider,
      model: template.model,
      temperature: template.temperature,
      max_tokens: template.max_tokens,
    });

    try {
      const parsed = JSON.parse(aiResponse);
      return parsed.description || undefined;
    } catch {
      // If not JSON, return raw text as description
      return aiResponse.trim() || undefined;
    }
  }

  /**
   * Generate troubleshooting steps for an incident ticket.
   */
  async generateTroubleshootingSteps(
    ticket: TicketData,
    settings: WorkflowSettings
  ): Promise<string | undefined> {
    if (!settings.ai_for_troubleshooting) return undefined;

    const template = await this.getTemplate('troubleshooting_steps');
    const systemPrompt = template?.system_prompt ||
      'You are an IT helpdesk assistant. Given a support ticket, generate 3-5 concise troubleshooting steps. Return JSON: {"steps": "numbered list of steps"}';

    const userTemplate = template?.user_prompt_template ||
      'Generate troubleshooting steps for this ticket:\n\nTitle: {{title}}\nDescription: {{description}}';

    const userPrompt = this.interpolate(userTemplate, {
      title: ticket.title,
      description: (ticket.description || '').substring(0, 2000),
    });

    const aiResponse = await this.callProvider(systemPrompt, userPrompt, settings, {
      provider: template?.provider,
      model: template?.model,
      temperature: template?.temperature ?? 0.3,
      max_tokens: template?.max_tokens ?? 1000,
    });

    try {
      const parsed = JSON.parse(aiResponse);
      return parsed.steps || undefined;
    } catch {
      return aiResponse.trim() || undefined;
    }
  }

  // ============================================================================
  // Default prompts (used when no template is configured in DB)
  // ============================================================================

  private getDefaultClassificationSystemPrompt(): string {
    return `You are an IT helpdesk ticket classifier. Given a ticket title and description, classify the ticket into the correct issue type, sub-issue type, ticket type, and priority.

Rules:
- ticket_type: 1 = Service Request, 2 = Incident
- Use the provided picklist data to select valid issue types and sub-issue types
- Ensure sub_issue_type parent_value matches the issue_type value
- Return ONLY valid picklist values

Return JSON format:
{"issueType": <number>, "subIssueType": <number>, "ticketType": <number>, "priority": <number>}`;
  }

  private getDefaultClassificationUserPrompt(): string {
    return `Classify this ticket. Only provide values for these fields that need classification: {{failed_fields}}

Title: {{title}}
Description: {{description}}
Ticket Category: {{ticket_category}}

Available Issue Types:
{{issueTypes}}

Available Sub-Issue Types (with parent_value):
{{subIssueTypes}}

Available Priorities:
{{priorities}}`;
  }
}

// Export singleton instance
export const aiTriageService = new AiTriageService();
