import { Injectable, Logger } from '@nestjs/common';

interface ChatMessage {
  role: 'user' | 'assistant' | 'system';
  content: string | { type: 'text' | 'image_url'; text?: string; image_url?: { url: string } }[];
}

export interface ChatOptions {
  temperature?: number;
  top_p?: number;
  max_tokens?: number;
}

export interface ModelInfo {
  id: string;
  provider: string;
  capabilities: string[];
  contextWindow: number;
}

interface AIProvider {
  name: string;
  chat(messages: ChatMessage[], options?: ChatOptions): Promise<string>;
  chatStream?(messages: ChatMessage[], options?: ChatOptions): AsyncIterable<string>;
}

// 仅收录沙箱实际可用的国内已备案大模型
const MODEL_CATALOG: Record<string, ModelInfo> = {
  'deepseek-v4-flash': { id: 'deepseek-v4-flash', provider: '硅基流动/DeepSeek', capabilities: ['chat', 'code'], contextWindow: 32768 },
  'sensenova-6.7-flash-lite': { id: 'sensenova-6.7-flash-lite', provider: '商汤科技', capabilities: ['chat', 'code'], contextWindow: 32768 },
};

/** 沙箱可选模型列表（前端展示用），modelId 必须与 MODEL_CATALOG 中的 id 一致 */
export const SANDBOX_MODELS = [
  { id: 'deepseek-v4-flash', label: 'DeepSeek V4 Flash', provider: '硅基流动', desc: '高速推理，代码生成能力强，价格极低', available: false },
  { id: 'sensenova-6.7-flash-lite', label: 'SenseNova 6.7 Flash Lite', provider: '商汤科技', desc: '轻量快速，日常对话与文本处理', available: false },
];

@Injectable()
export class AIGatewayService {
  private readonly logger = new Logger(AIGatewayService.name);
  private providers: Map<string, AIProvider> = new Map();
  private usageStats: Record<string, { total: number; success: number; failed: number }> = {};

  constructor() {
    this.registerProviders();
  }

  private registerProviders() {
    // 国内已备案大模型 — 通过硅基流动 / DeepSeek 直连等国内渠道
    if (process.env.OPENAI_API_KEY) {
      let apiUrl = process.env.OPENAI_API_URL || 'https://api.openai.com/v1/chat/completions';
      if (!apiUrl.endsWith('/chat/completions')) {
        apiUrl = apiUrl.replace(/\/+$/, '') + '/chat/completions';
      }
      const defaultModel = process.env.OPENAI_MODEL || 'deepseek/deepseek-v4-flash';
      this.providers.set('deepseek-v4-flash', new OpenAICompatibleProvider(
        process.env.OPENAI_API_KEY!,
        apiUrl,
        defaultModel,
        '硅基流动 / DeepSeek',
      ));
      this.logger.log(`DeepSeek(通过国内渠道)已注册: ${defaultModel}`);
      this.markAvailable('deepseek-v4-flash');
    }

    if (process.env.SENSENOVA_API_KEY) {
      let apiUrl = process.env.SENSENOVA_API_URL || 'https://token.sensenova.cn/v1';
      if (!apiUrl.endsWith('/chat/completions')) {
        apiUrl = apiUrl.replace(/\/+$/, '') + '/chat/completions';
      }
      // 商汤科技仅注册 sensenova 自有模型，避免覆盖硅基流动的 deepseek 注册
      const modelName = 'sensenova-6.7-flash-lite';
      this.providers.set(modelName, new OpenAICompatibleProvider(
        process.env.SENSENOVA_API_KEY!,
        apiUrl,
        modelName,
        '商汤科技',
      ));
      this.markAvailable(modelName);
      this.logger.log(`商汤科技已注册: ${modelName}`);
    }
  }

  /** 标记 SANDBOX_MODELS 中的对应模型为可用 */
  private markAvailable(modelId: string) {
    for (const m of SANDBOX_MODELS) {
      if (m.id === modelId) m.available = true;
    }
  }

  async chat(model: string, messages: ChatMessage[], options?: ChatOptions): Promise<string> {
    // 仅路由到国内已备案模型的 provider
    const modelMap: Record<string, string> = {
      'deepseek-v4-flash': 'deepseek-v4-flash',
      'sensenova-6.7-flash-lite': 'sensenova-6.7-flash-lite',
    };

    const providerKey = modelMap[model.toLowerCase()] || model;
    const provider = this.providers.get(providerKey);

    if (!this.usageStats[providerKey]) this.usageStats[providerKey] = { total: 0, success: 0, failed: 0 };
    this.usageStats[providerKey].total++;

    if (provider) {
      try {
        const reply = await provider.chat(messages, options);
        if (typeof reply !== 'string' || reply.length === 0) {
          throw new Error(`AI 返回内容为空: ${JSON.stringify(reply)}`);
        }
        this.usageStats[providerKey].success++;
        return reply;
      } catch (err: any) {
        this.logger.error(`${provider.name} 调用失败: ${err.message}`);
        this.usageStats[providerKey].failed++;
        return this.fallback(messages);
      }
    }

    return this.fallback(messages);
  }

  async *chatStream(model: string, messages: ChatMessage[], options?: ChatOptions): AsyncIterable<string> {
    const modelMap: Record<string, string> = {
      'deepseek-v4-flash': 'deepseek-v4-flash',
      'sensenova-6.7-flash-lite': 'sensenova-6.7-flash-lite',
    };

    const providerKey = modelMap[model.toLowerCase()] || model;
    const provider = this.providers.get(providerKey);

    if (!this.usageStats[providerKey]) this.usageStats[providerKey] = { total: 0, success: 0, failed: 0 };
    this.usageStats[providerKey].total++;

    if (provider?.chatStream) {
      try {
        let hasContent = false;
        for await (const chunk of provider.chatStream(messages, options)) {
          hasContent = true;
          yield chunk;
        }
        if (!hasContent) throw new Error('AI 返回内容为空');
        this.usageStats[providerKey].success++;
      } catch (err: any) {
        this.logger.error(`${provider.name} 流式调用失败: ${err.message}`);
        this.usageStats[providerKey].failed++;
        yield this.fallback(messages);
      }
    } else if (provider) {
      try {
        const reply = await provider.chat(messages, options);
        this.usageStats[providerKey].success++;
        yield reply;
      } catch (err: any) {
        this.logger.error(`${provider.name} 调用失败: ${err.message}`);
        this.usageStats[providerKey].failed++;
        yield this.fallback(messages);
      }
    } else {
      yield this.fallback(messages);
    }
  }

  private fallback(messages: ChatMessage[]): string {
    const lastMsg = typeof messages[messages.length - 1]?.content === 'string'
      ? messages[messages.length - 1]?.content as string : '';
    const mockReplies: Record<string, string> = {
      '你好': '你好！我是宇之然 AI 助手，很高兴为你服务！',
      'hello': 'Hello! I am YuZhiRan AI assistant, nice to meet you!',
    };

    for (const [key, reply] of Object.entries(mockReplies)) {
      if (lastMsg.toLowerCase().includes(key)) {
        return reply;
      }
    }

    if (lastMsg.includes('提示词') || lastMsg.includes('prompt')) {
      return '好的提示词需要明确角色、任务、输出格式和约束条件。例如："你是一名专业的文案编辑，请帮我优化以下产品描述，要求语言简洁有力，突出产品核心卖点，控制在200字以内。"';
    }

    if (lastMsg.includes('模型') || lastMsg.includes('大模型')) {
      return '目前主流的 AI 大模型包括：OpenAI 的 GPT 系列、Anthropic 的 Claude 系列、Google 的 Gemini 系列，以及国内的 DeepSeek、通义千问、文心一言、GLM 等。各模型在语言理解、代码生成、逻辑推理等方面各有优势。';
    }

    const names = Array.from(this.providers.values()).map(p => p.name).join('、');
    return `我是宇之然 AI 助手。关于"${lastMsg.slice(0, 50)}..."的问题，我已收到。当前 AI 沙箱处于模拟模式，请配置 API Key 以获取真实回复。已配置的 API：${names}。`;
  }

  getModelInfo(model: string): ModelInfo {
    const key = model.toLowerCase();
    return MODEL_CATALOG[key] || { id: model, provider: '未知', capabilities: ['chat'], contextWindow: 4096 };
  }

  getUsageStats() {
    return { ...this.usageStats };
  }

  getRegisteredProviders(): string[] {
    return Array.from(this.providers.keys());
  }

  /** 返回沙箱前端可选的模型列表（仅返回有 provider 注册的模型） */
  getSandboxModels() {
    return SANDBOX_MODELS.filter(m => m.available);
  }
}

class OpenAICompatibleProvider implements AIProvider {
  name: string;
  private apiKey: string;
  private apiUrl: string;
  private defaultModel: string;

  constructor(apiKey: string, apiUrl: string, defaultModel: string, name?: string) {
    this.apiKey = apiKey;
    this.apiUrl = apiUrl;
    this.defaultModel = defaultModel;
    this.name = name || 'OpenAI 兼容接口';
  }

  async chat(messages: ChatMessage[], options?: ChatOptions): Promise<string> {
    const res = await fetch(this.apiUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.apiKey}`,
      },
      body: JSON.stringify({
        model: this.defaultModel,
        messages,
        temperature: options?.temperature ?? 0.7,
        top_p: options?.top_p ?? 1,
        max_tokens: options?.max_tokens ?? 2000,
      }),
    });

    if (!res.ok) {
      throw new Error(`${this.name} API error: ${res.status} ${await res.text()}`);
    }

    const data = await res.json() as any;
    const msg = data.choices[0].message;
    return msg.content || msg.reasoning_content || '';
  }

  async *chatStream(messages: ChatMessage[], options?: ChatOptions): AsyncIterable<string> {
    const res = await fetch(this.apiUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.apiKey}`,
      },
      body: JSON.stringify({
        model: this.defaultModel,
        messages,
        temperature: options?.temperature ?? 0.7,
        top_p: options?.top_p ?? 1,
        max_tokens: options?.max_tokens ?? 2000,
        stream: true,
      }),
    });

    if (!res.ok) {
      throw new Error(`${this.name} API error: ${res.status} ${await res.text()}`);
    }

    const reader = res.body!.getReader();
    const decoder = new TextDecoder();
    let buffer = '';

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      buffer += decoder.decode(value, { stream: true });
      const lines = buffer.split('\n');
      buffer = lines.pop() || '';

      for (const line of lines) {
        const trimmed = line.trim();
        if (!trimmed || !trimmed.startsWith('data:')) continue;
        const data = trimmed.slice(5).trim();
        if (data === '[DONE]') return;
        try {
          const json = JSON.parse(data);
          const delta = json.choices?.[0]?.delta || {};
          const content = delta.content || delta.reasoning_content || '';
          if (content) yield content;
        } catch {}
      }
    }
  }
}
