/**
 * Social Engine — Phase 7: Performance Tracker
 * Collects engagement metrics for posted content and rolls up daily persona stats.
 * Uses user-context X API lookup for the bot's own posts, with fallback to public metrics.
 */
import {
  getRecentPostedForTracking,
  upsertPerformance,
  rollupDailyPersonaStats,
  getTractionExpansionCandidates,
  getRecentPersonaMemory,
  getSocialPostCountLastHours,
  insertContent,
  updateContentStatus,
} from './data-queries';
import { getTweetMetrics } from '../../twitter/services/twitter-api.service';
import { callGrokPersona } from './persona-prompts';
import { postTweet } from '../../twitter/services/twitter-api.service';
import type { PersonaConfig, SocialContentPiece } from './types';

const MAX_POSTS_PER_HOUR = parseInt(process.env.RAINMAKER_SOCIAL_MAX_POSTS_PER_HOUR || '1');

export async function trackPerformance(): Promise<void> {
  console.log('[social-engine] Performance tracker: Collecting metrics...');

  const posted = await getRecentPostedForTracking(48);

  if (posted.length === 0) {
    console.log('[social-engine] No recent posted content to track');
    return;
  }

  let tracked = 0;
  const chunks: typeof posted[] = [];
  for (let i = 0; i < posted.length; i += 50) {
    chunks.push(posted.slice(i, i + 50));
  }

  for (const chunk of chunks) {
    try {
      const metricsMap = await getTweetMetrics(chunk.map(item => item.tweet_id));

      for (const item of chunk) {
        const metrics = metricsMap[item.tweet_id] || {
          like_count: 0,
          retweet_count: 0,
          reply_count: 0,
          quote_count: 0,
          impression_count: 0,
        };

        const totalInteractions =
          (metrics.like_count || 0) +
          (metrics.retweet_count || 0) +
          (metrics.reply_count || 0) +
          (metrics.quote_count || 0);
        const impressions = metrics.impression_count || 0;
        const engagementRate = impressions > 0
          ? Number(((totalInteractions / impressions) * 100).toFixed(4))
          : 0;

        await upsertPerformance(item.id, item.tweet_id, item.persona_id, {
          impressions,
          likes: metrics.like_count || 0,
          retweets: metrics.retweet_count || 0,
          replies: metrics.reply_count || 0,
          quotes: metrics.quote_count || 0,
          engagement_rate: engagementRate,
        });
        tracked++;
      }
    } catch (err: any) {
      console.error('[social-engine] Metrics lookup failed:', err.message);
    }
  }

  await expandHighTractionPosts();
  console.log(`[social-engine] Tracked ${tracked} content pieces`);
}

export async function runDailyRollup(): Promise<void> {
  console.log('[social-engine] Running daily persona stats rollup...');
  try {
    await rollupDailyPersonaStats();
    console.log('[social-engine] Daily rollup complete');
  } catch (err: any) {
    console.error('[social-engine] Daily rollup failed:', err.message);
  }
}

async function expandHighTractionPosts(): Promise<void> {
  const socialPostedLastHour = await getSocialPostCountLastHours(1);
  if (socialPostedLastHour >= MAX_POSTS_PER_HOUR) {
    console.log(
      `[social-engine] Social hourly cap reached (${socialPostedLastHour}/${MAX_POSTS_PER_HOUR}), skipping traction follow-up`,
    );
    return;
  }

  const candidates = await getTractionExpansionCandidates(1);
  if (candidates.length === 0) return;

  const candidate = candidates[0];
  const persona: PersonaConfig = {
    id: candidate.persona_id,
    slug: candidate.persona_slug,
    display_name: candidate.persona_name,
    voice_style: candidate.voice_style,
    emoji_prefix: candidate.emoji_prefix,
    target_audience: candidate.target_audience,
    content_types: candidate.content_types,
    weight: candidate.weight,
    is_active: candidate.is_active,
  };

  const memory = await getRecentPersonaMemory(persona.id, 4);
  const prompt = `This post is getting traction. Write one follow-up self-reply in the same persona voice that adds a new angle.

ORIGINAL POST:
${candidate.text}

TRACTION SNAPSHOT:
- Impressions: ${candidate.impressions || 0}
- Likes: ${candidate.likes || 0}
- Replies: ${candidate.replies || 0}

Rules:
- Add new information or a sharper implication
- Keep it under 240 characters
- No generic CTA tail
- No repeated opener from recent posts
- One reply only, not a full thread
${memory.length ? `\nRECENT PERSONA POSTS TO AVOID COPYING:\n${memory.map((item, index) => `${index + 1}. ${item.slice(0, 140)}`).join('\n')}` : ''}`;

  const result = await callGrokPersona(prompt, persona);
  const replyText = result?.text?.trim();
  if (!replyText || replyText.length < 20) return;

  try {
    const postResult = await postTweet(replyText.slice(0, 240), candidate.tweet_id);
    const piece: SocialContentPiece = {
      persona_id: persona.id,
      trend_id: candidate.trend_id,
      content_type: candidate.content_type,
      format: 'thread_reply',
      text: replyText.slice(0, 240),
      league: candidate.league || undefined,
      sport: candidate.sport || undefined,
      game_key: candidate.game_key || undefined,
      source_data: {
        ...(candidate.source_data || {}),
        triggered_by: 'traction_followup',
        parent_tweet_id: candidate.tweet_id,
      },
      quality_score: candidate.engagement_rate || candidate.impressions || 0,
      status: postResult.tweetId.startsWith('dry_') ? 'preview' : 'posted',
      parent_content_id: candidate.id,
      thread_position: 1,
    };

    const contentId = await insertContent(piece);
    await updateContentStatus(contentId, piece.status || 'posted', {
      tweet_id: postResult.tweetId,
      posted_at: new Date(),
    });
    console.log(`[social-engine] Traction follow-up posted for ${candidate.tweet_id} → ${postResult.tweetId}`);
  } catch (err: any) {
    console.error('[social-engine] Traction follow-up failed:', err.message);
  }
}
