import { addCognitiveLog } from '../db.mjs';
import { askLLM, pickModel } from '../llm.mjs';
import { parseLLMJson } from '../json-utils.mjs';
import { getConfig } from '../config.mjs';

const DEFAULT_PERSPECTIVES = ['Pragmatist', 'Critic', 'Optimist', 'Engineer'];

export async function think(question, context = '', depth = null) {
  const config = getConfig();
  depth = depth || config.cognitive?.thinkerDepth || 'balanced';
  const passes = depth === 'fast' ? 1 : depth === 'deep' ? 3 : 2;
  const model = passes >= 3 ? pickModel('discuss') : pickModel('reflect');
  const start = Date.now();

  try {
    // Pass 1: Initial reasoning
    const p1Prompt = `Think step-by-step about this question.
Question: ${question}
${context ? `Context: ${context}` : ''}

Return JSON: { "reasoning": "step-by-step chain of thought", "conclusion": "concise answer", "confidence": 0-100 }`;

    const p1Response = await askLLM(p1Prompt, { model });
    const p1 = parseLLMJson(p1Response);
    if (!p1.ok) throw new Error('Failed to parse thinking response');

    let result = { reasoning: p1.data.reasoning, conclusion: p1.data.conclusion, confidence: p1.data.confidence || 50, depth_used: depth };

    if (passes >= 2) {
      // Pass 2: Self-critique
      const p2Prompt = `Review this reasoning for logical flaws, missing considerations, or biases.
Original reasoning: ${result.reasoning}
Original conclusion: ${result.conclusion}

Return JSON: { "reasoning": "revised step-by-step reasoning", "conclusion": "revised conclusion", "confidence": 0-100 }`;

      try {
        const p2Response = await askLLM(p2Prompt, { model });
        const p2 = parseLLMJson(p2Response);
        if (p2.ok) {
          result.reasoning = p2.data.reasoning || result.reasoning;
          result.conclusion = p2.data.conclusion || result.conclusion;
          result.confidence = p2.data.confidence || result.confidence;
        }
      } catch {}
    }

    if (passes >= 3) {
      // Pass 3: Alternative angle
      const p3Prompt = `Consider the opposite perspective or an unconventional approach to this question.
Question: ${question}
Current conclusion: ${result.conclusion}

Return JSON: { "alternative_view": "...", "revised_conclusion": "...", "confidence": 0-100 }`;

      try {
        const p3Response = await askLLM(p3Prompt, { model });
        const p3 = parseLLMJson(p3Response);
        if (p3.ok && p3.data.revised_conclusion) {
          result.reasoning += `\n\nAlternative view: ${p3.data.alternative_view}`;
          result.conclusion = p3.data.revised_conclusion;
          result.confidence = p3.data.confidence || result.confidence;
        }
      } catch {}
    }

    const durationMs = Date.now() - start;
    addCognitiveLog('thinker', question.slice(0, 200), result.conclusion?.slice(0, 500) || '', 0, durationMs, JSON.stringify({ depth, passes }));
    return result;
  } catch (err) {
    addCognitiveLog('thinker', question.slice(0, 200), `Failed: ${err.message}`, 0, Date.now() - start);
    throw err;
  }
}

export async function discuss(topic, perspectives = null, context = '') {
  const persList = perspectives || DEFAULT_PERSPECTIVES;
  const model = pickModel('discuss');
  const start = Date.now();
  const results = [];

  try {
    for (const perspective of persList) {
      const prompt = `You are a ${perspective}. Discuss this topic from your perspective.
Topic: ${topic}
${context ? `Context: ${context}` : ''}

Return JSON: { "argument": "your position and reasoning as a ${perspective}" }`;

      try {
        const response = await askLLM(prompt, { model });
        const parsed = parseLLMJson(response);
        if (parsed.ok) {
          results.push({ name: perspective, argument: parsed.data.argument || response });
        } else {
          results.push({ name: perspective, argument: response.slice(0, 500) });
        }
      } catch {
        results.push({ name: perspective, argument: `(${perspective} perspective unavailable)` });
      }
    }

    // Synthesize
    const synthPrompt = `Given these perspectives on "${topic}":
${results.map(r => `${r.name}: ${r.argument}`).join('\n\n')}

Synthesize a balanced conclusion. Return JSON: { "synthesis": "balanced conclusion considering all perspectives" }`;

    const synthResponse = await askLLM(synthPrompt, { model });
    const synthParsed = parseLLMJson(synthResponse);
    const synthesis = synthParsed.ok ? synthParsed.data.synthesis : synthResponse.slice(0, 500);

    const durationMs = Date.now() - start;
    addCognitiveLog('thinker', `discuss: ${topic}`, synthesis?.slice(0, 500) || '', 0, durationMs, JSON.stringify({ perspectives: persList }));
    return { perspectives: results, synthesis };
  } catch (err) {
    addCognitiveLog('thinker', `discuss: ${topic}`, `Failed: ${err.message}`, 0, Date.now() - start);
    throw err;
  }
}

export async function decompose(problem) {
  const model = pickModel('plan');
  const start = Date.now();

  try {
    const prompt = `Decompose this problem into 2-5 smaller, independent subproblems.
Problem: ${problem}

Return JSON: { "subproblems": [{ "description": "...", "approach": "suggested approach", "complexity": "low|medium|high" }] }`;

    const response = await askLLM(prompt, { model });
    const parsed = parseLLMJson(response);
    if (!parsed.ok) throw new Error('Failed to parse decomposition');

    const result = { subproblems: parsed.data.subproblems || [] };
    const durationMs = Date.now() - start;
    addCognitiveLog('thinker', `decompose: ${problem.slice(0, 200)}`, `${result.subproblems.length} subproblems`, 0, durationMs);
    return result;
  } catch (err) {
    addCognitiveLog('thinker', `decompose: ${problem.slice(0, 200)}`, `Failed: ${err.message}`, 0, Date.now() - start);
    throw err;
  }
}

export { DEFAULT_PERSPECTIVES };
