/**
 * Social Engine — Phase 4: Content Multiplier
 * Expands high-heat content into threads and generates FLUX images for visual posts.
 */
import * as crypto from 'crypto';
import * as fs from 'fs';
import * as path from 'path';
import { execSync } from 'child_process';
import { createCanvas, registerFont } from 'canvas';
import pool from '../../db';
import { insertContent, updateContentStatus } from './data-queries';
import { callGrokPersona } from './persona-prompts';
import type { PersonaConfig, SocialContentPiece } from './types';
import { generateFluxMacImage, isFluxMacEnabled } from '../../services/flux-mac-images';
import { generateKieImageWithMeta } from '../../services/kie-images';
import { buildFluxSocialImagePrompt } from './social-image-prompts';

const SOCIAL_CARDS_DIR = '/var/www/html/rainmaker/public/social-cards';
const MAX_THREADS_PER_CYCLE = 1;

const SPORT_COLORS: Record<string, string> = {
  nfl: '#013369',
  nba: '#C8102E',
  mlb: '#002D72',
  nhl: '#111111',
  soccer: '#00FF87',
  mma: '#D20A2E',
  ncaab: '#FF6B00',
  ncaaf: '#552583',
  epl: '#00FF87',
  general: '#f97316',
};

try {
  registerFont('/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf', {
    family: 'LiberationSans',
    weight: 'bold',
  });
} catch {
  // Canvas can still render with fallback fonts.
}

export async function multiplyContent(): Promise<number> {
  console.log('[social-engine] Phase 4: Multiplying high-heat content...');

  // Get recent draft content with high quality scores that could benefit from threads/images
  const result = await pool.query(
    `SELECT c.*, p.slug as persona_slug, p.display_name as persona_name,
            p.voice_style, p.emoji_prefix, p.target_audience, p.content_types, p.weight, p.is_active
     FROM rm_social_content c
     JOIN rm_social_personas p ON c.persona_id = p.id
     WHERE c.status = 'draft' AND c.format = 'tweet'
     AND c.created_at > NOW() - INTERVAL '2 hours'
     ORDER BY c.quality_score DESC NULLS LAST LIMIT 10`
  );

  let multiplied = 0;
  let threadsExpanded = 0;

  for (const row of result.rows) {
    const heat = row.quality_score || 0;
    const persona: PersonaConfig = {
      id: row.persona_id,
      slug: row.persona_slug,
      display_name: row.persona_name,
      voice_style: row.voice_style,
      emoji_prefix: row.emoji_prefix,
      target_audience: row.target_audience,
      content_types: row.content_types,
      weight: row.weight,
      is_active: row.is_active,
    };

    const threadEligible =
      heat > 85 &&
      threadsExpanded < MAX_THREADS_PER_CYCLE &&
      (persona.slug === 'the_sharp' || persona.slug === 'the_educator') &&
      ['forecast_pick', 'model_explainer', 'trend_breakdown', 'stat_deep_dive'].includes(row.content_type);

    // Expand only the strongest analytical posts to avoid noisy fragmented feeds.
    if (threadEligible) {
      const threadCount = await expandToThread(row, persona);
      if (threadCount > 0) {
        // Update original to thread format
        await pool.query(
          `UPDATE rm_social_content SET format = 'thread_head' WHERE id = $1`,
          [row.id]
        );
        multiplied += threadCount;
        threadsExpanded++;
      }
    }

    // Image generation: heat > 60 and has an image prompt
    if (heat > 60 && row.image_prompt) {
      const imageUrl = await generateSocialImage(row.image_prompt, row.id, row.sport || undefined);
      if (imageUrl) {
        await updateContentStatus(row.id, 'draft', { image_url: imageUrl });
        multiplied++;
      }
    }
  }

  console.log(`[social-engine] Phase 4 complete: ${multiplied} expansions`);
  return multiplied;
}

async function expandToThread(content: any, persona: PersonaConfig): Promise<number> {
  try {
    const prompt = `The following tweet was written in your voice. Expand it into 2 follow-up tweets that form a thread.

ORIGINAL TWEET:
${content.text}

Return JSON: { "thread": ["follow-up tweet 1", "follow-up tweet 2"] }

Rules:
- Each follow-up should add NEW information, not repeat
- First follow-up: deeper data/analysis
- Second follow-up: call to action or forward-looking take
- Keep your persona voice consistent
- Each tweet can be up to 280 chars for punchiness (even though X Premium allows more)`;

    const result = await callGrokPersona(prompt, persona);
    if (!result) return 0;

    // Parse thread array from response
    let threadParts: string[] = [];
    const parsed = result as any;
    if (parsed.thread && Array.isArray(parsed.thread)) {
      threadParts = parsed.thread;
    } else if (parsed.text) {
      // Grok returned text instead of thread array — skip
      return 0;
    }

    let inserted = 0;
    for (let i = 0; i < threadParts.length; i++) {
      const part = threadParts[i];
      if (!part || part.length < 10) continue;

      const piece: SocialContentPiece = {
        persona_id: content.persona_id,
        trend_id: content.trend_id,
        content_type: content.content_type,
        format: 'thread_reply',
        text: part,
        league: content.league,
        sport: content.sport,
        game_key: content.game_key,
        source_data: content.source_data,
        quality_score: content.quality_score,
        status: 'draft',
        parent_content_id: content.id,
        thread_position: i + 1,
      };

      await insertContent(piece);
      inserted++;
    }

    return inserted;
  } catch (err: any) {
    console.error(`[social-engine] Thread expansion failed:`, err.message);
    return 0;
  }
}

async function generateSocialImage(imagePrompt: string, contentId: string, sport?: string): Promise<string | null> {
  const { prompt: visualPrompt, negativePrompt } = buildFluxSocialImagePrompt(imagePrompt, sport);
  try {
    let generationSource = 'canvas_fallback';
    let generationMeta: Record<string, unknown> = {};
    let buffer: Buffer | null = null;

    if (isFluxMacEnabled()) {
      try {
        const fluxResult = await generateFluxMacImage(visualPrompt, {
          negativePrompt,
          filenamePrefix: `social-${contentId.slice(0, 12)}`,
        });

        if (fluxResult?.buffer) {
          buffer = fluxResult.buffer;
          generationSource = 'flux_mac';
          generationMeta = {
            flux_server: fluxResult.server,
            flux_model_preset: fluxResult.modelPreset,
            flux_realism_preset: fluxResult.realismPreset,
            flux_seed: fluxResult.seed,
          };
        }
      } catch (err: any) {
        console.error('[social-engine] Flux Mac image failed:', err.message);
      }
    }

    if (!buffer) {
      const kieResult = await generateKieImageWithMeta(visualPrompt, {
        category: 'social_engine',
        subcategory: 'image_generation',
        aspectRatio: '16:9',
      });
      buffer = kieResult.buffer;
      if (buffer) {
        generationSource = `kie_${kieResult.completionSource || 'unknown'}`;
      }
    }

    if (!buffer) {
      buffer = generateFallbackCard(visualPrompt, sport);
    }

    // Write to social-cards directory
    if (!fs.existsSync(SOCIAL_CARDS_DIR)) {
      fs.mkdirSync(SOCIAL_CARDS_DIR, { recursive: true });
    }

    const hash = crypto.createHash('sha256').update(contentId).digest('hex').slice(0, 12);
    const pngPath = path.join(SOCIAL_CARDS_DIR, `${hash}.png`);
    const webpPath = path.join(SOCIAL_CARDS_DIR, `${hash}.webp`);
    const filename = `${hash}.webp`;

    // Write PNG temporarily, convert to WebP (quality 82 — optimal size/quality), remove PNG
    fs.writeFileSync(pngPath, buffer);
    try {
      execSync(`cwebp -q 82 "${pngPath}" -o "${webpPath}"`, { timeout: 15000 });
      fs.unlinkSync(pngPath);
      const webpSize = fs.statSync(webpPath).size;
      console.log(`[social-engine] Image optimized: ${(buffer.length / 1024).toFixed(0)}KB PNG → ${(webpSize / 1024).toFixed(0)}KB WebP`);
    } catch {
      // Fallback: serve the PNG if cwebp fails
      console.warn('[social-engine] WebP conversion failed, using PNG');
      return `/api/social-cards/${hash}.png`;
    }

    const webpSize = fs.existsSync(webpPath) ? fs.statSync(webpPath).size : buffer.length;
    pool.query(
      `INSERT INTO rm_api_usage (category, subcategory, provider, model, response_time_ms, success, metadata)
       VALUES ($1, $2, $3, $4, $5, true, $6)`,
      ['social_engine', 'image_processing', 'local', 'cwebp', 0,
       JSON.stringify({
         prompt_length: visualPrompt.length,
         original_size: buffer.length,
         webp_size: webpSize,
          generation_source: generationSource,
          flux_enabled: isFluxMacEnabled(),
          negative_prompt_length: negativePrompt.length,
          ...generationMeta,
       })]
    ).catch(() => {});

    return `/api/social-cards/${filename}`;
  } catch (err: any) {
    console.error(`[social-engine] Kie image failed:`, err.message);
    return null;
  }
}

function wrapText(ctx: any, text: string, maxWidth: number, maxLines: number): string[] {
  const words = text.split(/\s+/).filter(Boolean);
  const lines: string[] = [];
  let currentLine = '';

  for (const word of words) {
    const testLine = currentLine ? `${currentLine} ${word}` : word;
    if (ctx.measureText(testLine).width > maxWidth && currentLine) {
      lines.push(currentLine);
      currentLine = word;
      if (lines.length >= maxLines) break;
    } else {
      currentLine = testLine;
    }
  }

  if (currentLine && lines.length < maxLines) {
    lines.push(currentLine);
  }

  return lines;
}

function generateFallbackCard(text: string, sport?: string): Buffer {
  const W = 1200;
  const H = 675;
  const canvas = createCanvas(W, H);
  const ctx = canvas.getContext('2d');
  const accent = SPORT_COLORS[(sport || '').toLowerCase()] || SPORT_COLORS.general;

  const bg = ctx.createLinearGradient(0, 0, W, H);
  bg.addColorStop(0, '#0a0c12');
  bg.addColorStop(1, '#171b25');
  ctx.fillStyle = bg;
  ctx.fillRect(0, 0, W, H);

  ctx.fillStyle = accent;
  ctx.fillRect(0, 0, W, 8);

  ctx.fillStyle = 'rgba(255,255,255,0.08)';
  ctx.beginPath();
  ctx.arc(W - 180, 140, 120, 0, Math.PI * 2);
  ctx.fill();

  ctx.font = 'bold 22px LiberationSans, Arial, sans-serif';
  ctx.fillStyle = accent;
  ctx.fillText('RAINMAKER SOCIAL', 72, 88);

  ctx.font = 'bold 54px LiberationSans, Arial, sans-serif';
  ctx.fillStyle = '#ffffff';
  const lines = wrapText(ctx, text, W - 144, 5);
  lines.forEach((line, index) => {
    ctx.fillText(line, 72, 180 + index * 72);
  });

  ctx.font = 'bold 20px LiberationSans, Arial, sans-serif';
  ctx.fillStyle = 'rgba(255,255,255,0.4)';
  ctx.fillText((sport || 'general').toUpperCase(), 72, H - 72);

  return canvas.toBuffer('image/png');
}
