/**
 * LOOPUMAN ON-CHAIN REPUTATION SERVICE
 * 
 * Records worker reputation on Celo blockchain using transaction data field.
 * Tracks: speed, quality, category expertise, task count, ratings.
 * Cost: ~$0.001 per attestation (0 CELO transfer with data).
 */
'use strict';
const { ethers } = require('ethers');
const { createClient } = require('@supabase/supabase-js');
const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_SERVICE_KEY);

const CONFIG = {
  RPC_URL: process.env.CELO_RPC_URL || 'https://forno.celo.org',
  PLATFORM_WALLET_KEY: process.env.CELO_PRIVATE_KEY || process.env.PLATFORM_WALLET_PRIVATE_KEY,
  ENABLED: process.env.REPUTATION_ENABLED !== 'false',
  MILESTONES: [
    { tasks: 10, badge: 'Rising Star', emoji: '⭐' },
    { tasks: 25, badge: 'Reliable', emoji: '🌟' },
    { tasks: 50, badge: 'Trusted', emoji: '✨' },
    { tasks: 100, badge: 'Expert', emoji: '💫' },
    { tasks: 250, badge: 'Elite', emoji: '🏆' },
    { tasks: 500, badge: 'Master', emoji: '👑' },
    { tasks: 1000, badge: 'Legendary', emoji: '🌈' },
  ],
  CELOSCAN_URL: 'https://celoscan.io/tx/',
};

function getMilestone(taskCount) {
  let milestone = null;
  for (const m of CONFIG.MILESTONES) {
    if (taskCount >= m.tasks) milestone = m;
  }
  return milestone;
}

function isNewMilestone(taskCount) {
  return CONFIG.MILESTONES.some(m => m.tasks === taskCount);
}

class ReputationService {
  constructor() {
    this.provider = null;
    this.wallet = null;
    this.ready = false;
  }

  async initialize() {
    if (this.ready) return true;
    try {
      if (!CONFIG.PLATFORM_WALLET_KEY) {
        console.log('[Reputation] No wallet key, disabled');
        return false;
      }
      this.provider = new ethers.JsonRpcProvider(CONFIG.RPC_URL);
      this.wallet = new ethers.Wallet(CONFIG.PLATFORM_WALLET_KEY, this.provider);
      this.ready = true;
      console.log('[Reputation] Initialized, wallet:', this.wallet.address);
      return true;
    } catch (e) {
      console.error('[Reputation] Init failed:', e.message);
      return false;
    }
  }

  async getWorkerStats(workerId) {
    const { data: worker } = await supabase.from('users')
      .select('id, wallet_address, tasks_completed, avg_rating, review_count, created_at')
      .eq('id', workerId).single();
    if (!worker) return null;

    const { data: subs } = await supabase.from('submissions')
      .select('id, task_id, created_at, submitted_at, status, tasks(category, budget_vae, created_at)')
      .eq('worker_id', workerId)
      .eq('status', 'approved')
      .order('created_at', { ascending: false })
      .limit(100);

    // Speed metrics
    const speeds = (subs || []).map(s => {
      if (!s.tasks?.created_at || !s.submitted_at) return null;
      return (new Date(s.submitted_at) - new Date(s.tasks.created_at)) / 60000;
    }).filter(Boolean);
    const avgSpeedMin = speeds.length > 0 ? Math.round(speeds.reduce((a, b) => a + b, 0) / speeds.length) : null;
    const fastestMin = speeds.length > 0 ? Math.round(Math.min(...speeds)) : null;

    // Category expertise
    const cats = {};
    (subs || []).forEach(s => {
      const c = s.tasks?.category || 'other';
      cats[c] = (cats[c] || 0) + 1;
    });
    const topCategories = Object.entries(cats).sort((a, b) => b[1] - a[1]).slice(0, 5)
      .map(([category, completed]) => ({ category, completed }));

    const totalEarned = (subs || []).reduce((sum, s) => sum + (s.tasks?.budget_vae || 0) * 0.8, 0);
    const milestone = getMilestone(worker.tasks_completed || 0);

    return {
      worker_id: workerId,
      wallet_address: worker.wallet_address,
      tasks_completed: worker.tasks_completed || 0,
      avg_rating: worker.avg_rating || 0,
      review_count: worker.review_count || 0,
      avg_speed_minutes: avgSpeedMin,
      fastest_minutes: fastestMin,
      total_earned_vae: Math.round(totalEarned),
      top_categories: topCategories,
      member_since: worker.created_at,
      milestone: milestone ? { badge: milestone.badge, emoji: milestone.emoji } : null,
      reputation_score: this.calculateScore(worker, avgSpeedMin, speeds.length),
    };
  }

  calculateScore(worker, avgSpeed, completedCount) {
    let score = 0;
    const tasks = worker.tasks_completed || 0;
    score += Math.min(30, Math.log2(tasks + 1) * 4.3);
    score += ((worker.avg_rating || 0) / 5) * 30;
    if (avgSpeed && avgSpeed > 0) score += Math.min(20, Math.max(0, (60 - avgSpeed) / 60 * 20));
    score += Math.min(20, completedCount * 0.4);
    return Math.round(Math.min(100, score));
  }

  async recordOnChain(workerId) {
    if (!CONFIG.ENABLED || !this.ready) return null;
    try {
      const stats = await this.getWorkerStats(workerId);
      if (!stats || !stats.wallet_address) return null;
      if (!isNewMilestone(stats.tasks_completed)) return null;

      const attestation = {
        platform: 'loopuman', version: 2,
        worker: stats.wallet_address,
        tasks_completed: stats.tasks_completed,
        avg_rating: stats.avg_rating,
        reputation_score: stats.reputation_score,
        avg_speed_minutes: stats.avg_speed_minutes,
        top_categories: stats.top_categories.map(c => c.category),
        milestone: stats.milestone?.badge,
        timestamp: Math.floor(Date.now() / 1000),
      };

      const dataHex = ethers.hexlify(ethers.toUtf8Bytes(JSON.stringify(attestation)));
      const tx = await this.wallet.sendTransaction({ to: stats.wallet_address, value: 0n, data: dataHex });
      const receipt = await tx.wait();
      console.log(`[Reputation] On-chain: ${stats.milestone?.badge} ${CONFIG.CELOSCAN_URL}${receipt.hash}`);

      // Store in DB (ignore if table doesn't exist yet)
      try {
        await supabase.from('reputation_attestations').upsert({
          worker_id: workerId, wallet_address: stats.wallet_address,
          tx_hash: receipt.hash, tasks_completed: stats.tasks_completed,
          avg_rating: stats.avg_rating, reputation_score: stats.reputation_score,
          milestone: stats.milestone?.badge, attestation_data: attestation,
          created_at: new Date().toISOString(),
        }, { onConflict: 'worker_id,milestone' });
      } catch (dbErr) { console.log('[Reputation] DB store skipped:', dbErr.message); }

      return {
        tx_hash: receipt.hash,
        celoscan_url: `${CONFIG.CELOSCAN_URL}${receipt.hash}`,
        milestone: stats.milestone,
        reputation_score: stats.reputation_score,
      };
    } catch (e) {
      console.error('[Reputation] On-chain error:', e.message);
      return null;
    }
  }
}

module.exports = { ReputationService, getMilestone, isNewMilestone };
