import { getEvents } from './db.mjs';
import { getConfig } from './config.mjs';
import { parseLLMJson } from './json-utils.mjs';
import { loadEvolution, saveEvolution } from './evolution.mjs';

function since24h() {
  return new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString().replace('T', ' ').slice(0, 19);
}

/**
 * Check whether the daily reflection should run.
 * Returns true if:
 *   - cognitive.dailyReflection is not false
 *   - The most recent reflection event is more than 20 hours old (or none exists)
 */
export function shouldRunReflection(config, _db) {
  const cogConfig = (config || getConfig()).cognitive || {};
  if (cogConfig.dailyReflection === false) return false;

  const recent = getEvents({ type: 'reflection', limit: 1 });
  if (!recent.length) return true;

  const lastAt = new Date(recent[0].created_at.replace(' ', 'T') + 'Z').getTime();
  const hoursSince = (Date.now() - lastAt) / (1000 * 60 * 60);
  return hoursSince > 20;
}

/**
 * Run the daily meta-reflection cycle.
 * Queries the last 24 hours of activity, asks the LLM to reflect, stores the
 * result as a 'reflection' event, and optionally adjusts capability scores.
 */
export async function runDailyReflection({ askLLM, pickModel, addEvent, db: _db, getConfig: getConfigFn }) {
  const cfg = getConfigFn ? getConfigFn() : getConfig();
  const cutoff = since24h();

  // Gather last 24h of events (up to 500)
  const events = getEvents({ since: cutoff, limit: 500 });

  // Count activity metrics
  const messageCount = events.filter(e => e.type === 'chat' && e.source === 'user').length;
  const skillsRun   = events.filter(e => e.type === 'system' && e.source === 'agent' && e.content.includes('Queued task')).length;
  const filesCreated = events.filter(e => e.type === 'system' && e.source === 'agent' && /file (created|change|watcher)|built page|wrote doc/i.test(e.content)).length;
  const errorCount  = events.filter(e => e.type === 'error').length;

  // User feedback signals
  const thumbsUp   = events.filter(e => e.type === 'feedback' && /thumbs.?up/i.test(e.content)).length;
  const thumbsDown = events.filter(e => e.type === 'feedback' && /thumbs.?down/i.test(e.content)).length;

  // Error patterns (first 100 chars each, up to 10)
  const errorLines = events
    .filter(e => e.type === 'error')
    .slice(0, 10)
    .map(e => `  - ${e.content.slice(0, 100)}`)
    .join('\n');

  // Capability scores from evolution state
  let capabilityContext = '';
  let evolutionState = null;
  try {
    evolutionState = await loadEvolution();
    const caps = evolutionState.capability_scores || {};
    capabilityContext = Object.entries(caps)
      .map(([k, v]) => `  - ${k}: ${Math.round(Number(v) * 100)}%`)
      .join('\n');
  } catch {}

  const activitySummary = [
    `Messages processed: ${messageCount}`,
    `Skills executed:    ${skillsRun}`,
    `Files created:      ${filesCreated}`,
    `Errors encountered: ${errorCount}`,
    `User thumbs up:     ${thumbsUp}`,
    `User thumbs down:   ${thumbsDown}`
  ].join('\n');

  const prompt = `You are an autonomous AI agent conducting your daily self-reflection to continuously improve.

## Activity Summary (Last 24 Hours)
${activitySummary}

## Error Patterns
${errorLines || '  (no errors)'}

## Current Capability Scores
${capabilityContext || '  (not available)'}

Produce a structured daily reflection. Return JSON only:
{
  "went_well": ["what worked well today"],
  "could_improve": ["areas needing improvement"],
  "suggestions": ["1-3 specific, actionable steps to improve in the next 24 hours"],
  "capability_adjustments": {}
}

Rules:
- "suggestions" must be concrete and implementable, not vague.
- "capability_adjustments" maps capability name → small delta (−0.05 to +0.05).
  Only include capabilities that clearly improved or regressed today.
  Leave empty ({}) if activity was too low to draw conclusions.`;

  const raw = await askLLM(prompt, { model: pickModel('reflect') });
  const parsed = parseLLMJson(raw);

  let reflectionText = '';

  if (parsed.ok && parsed.data) {
    const d = parsed.data;
    const fmt = (arr) => (Array.isArray(arr) && arr.length ? arr.map(s => `  - ${s}`).join('\n') : '  (none)');

    reflectionText = [
      'Daily Reflection',
      '',
      'What went well:',
      fmt(d.went_well),
      '',
      'What could improve:',
      fmt(d.could_improve),
      '',
      'Actionable suggestions:',
      fmt(d.suggestions)
    ].join('\n');

    // Apply capability score adjustments if suggested
    if (evolutionState && d.capability_adjustments && typeof d.capability_adjustments === 'object') {
      let changed = false;
      const caps = evolutionState.capability_scores || {};
      for (const [cap, delta] of Object.entries(d.capability_adjustments)) {
        if (cap in caps && typeof delta === 'number' && isFinite(delta)) {
          const clamped = Math.max(-0.05, Math.min(0.05, delta));
          const current = Number(caps[cap] || 0);
          caps[cap] = Math.max(0, Math.min(1, Number((current + clamped).toFixed(3))));
          evolutionState.capability_scores = caps;
          changed = true;
        }
      }
      if (changed) {
        try { await saveEvolution(); } catch {}
      }
    }
  } else {
    // LLM returned non-JSON; store raw output trimmed
    reflectionText = `Daily Reflection\n\n${raw.slice(0, 1000)}`;
  }

  addEvent('reflection', 'agent', reflectionText);
  console.log('[meta-reflection] Daily reflection complete');
  return reflectionText;
}
