/**
 * TransportTrackerAgent
 * Monitors transport events and calculates environmental impact
 *
 * Responsibilities:
 * - Track seed-to-seed transport lifecycle
 * - Calculate and aggregate carbon footprint
 * - Monitor food miles across the network
 * - Detect inefficient transport patterns
 * - Generate transport optimization recommendations
 */

import { BaseAgent } from './BaseAgent';
import { AgentConfig, AgentTask } from './types';
import { getTransportChain } from '../transport/tracker';
import {
  TransportEvent,
  TransportMethod,
  TransportEventType,
  CARBON_FACTORS
} from '../transport/types';

interface TransportAnalysis {
  userId: string;
  totalEvents: number;
  totalDistanceKm: number;
  totalCarbonKg: number;
  carbonPerKm: number;
  mostUsedMethod: TransportMethod;
  methodBreakdown: Record<TransportMethod, { count: number; distance: number; carbon: number }>;
  eventTypeBreakdown: Record<TransportEventType, number>;
  efficiency: 'excellent' | 'good' | 'average' | 'poor';
  recommendations: string[];
}

interface TransportPattern {
  type: 'inefficient_route' | 'high_carbon' | 'excessive_handling' | 'cold_chain_break';
  description: string;
  affectedEvents: string[];
  potentialSavingsKg: number;
  severity: 'low' | 'medium' | 'high';
}

interface NetworkTransportStats {
  totalEvents: number;
  totalDistanceKm: number;
  totalCarbonKg: number;
  avgCarbonPerEvent: number;
  avgDistancePerEvent: number;
  greenTransportPercentage: number;
  methodDistribution: Record<TransportMethod, number>;
  dailyTrends: { date: string; events: number; carbon: number }[];
}

export class TransportTrackerAgent extends BaseAgent {
  private userAnalytics: Map<string, TransportAnalysis> = new Map();
  private detectedPatterns: TransportPattern[] = [];
  private networkStats: NetworkTransportStats | null = null;

  constructor() {
    const config: AgentConfig = {
      id: 'transport-tracker-agent',
      name: 'Transport Tracker Agent',
      description: 'Monitors transport events and environmental impact',
      enabled: true,
      intervalMs: 120000, // Run every 2 minutes
      priority: 'high',
      maxRetries: 3,
      timeoutMs: 30000
    };
    super(config);
  }

  /**
   * Main execution cycle
   */
  async runOnce(): Promise<AgentTask | null> {
    const transportChain = getTransportChain();
    const chain = transportChain.chain;

    // Skip genesis block
    const events = chain.slice(1).map(b => b.transportEvent);

    // Update network statistics
    this.networkStats = this.calculateNetworkStats(events);

    // Analyze by user
    this.analyzeUserPatterns(events);

    // Detect inefficient patterns
    const newPatterns = this.detectInefficiencies(events);
    this.detectedPatterns = [...this.detectedPatterns, ...newPatterns].slice(-100);

    // Generate alerts for critical patterns
    for (const pattern of newPatterns) {
      if (pattern.severity === 'high') {
        this.createAlert('warning', `Transport Issue: ${pattern.type}`,
          pattern.description,
          { actionRequired: `Potential savings: ${pattern.potentialSavingsKg.toFixed(2)} kg CO2` }
        );
      }
    }

    // Check for milestone achievements
    this.checkMilestones();

    return this.createTaskResult('transport_analysis', 'completed', {
      eventsAnalyzed: events.length,
      usersTracked: this.userAnalytics.size,
      patternsDetected: newPatterns.length,
      networkCarbonKg: this.networkStats?.totalCarbonKg || 0
    });
  }

  /**
   * Calculate network-wide statistics
   */
  private calculateNetworkStats(events: TransportEvent[]): NetworkTransportStats {
    const methodCounts: Record<TransportMethod, number> = {} as any;
    const dailyMap = new Map<string, { events: number; carbon: number }>();

    let totalDistance = 0;
    let totalCarbon = 0;
    let greenEvents = 0;

    const greenMethods: TransportMethod[] = ['walking', 'bicycle', 'electric_vehicle', 'electric_truck', 'rail'];

    for (const event of events) {
      totalDistance += event.distanceKm;
      totalCarbon += event.carbonFootprintKg;

      // Method distribution
      methodCounts[event.transportMethod] = (methodCounts[event.transportMethod] || 0) + 1;

      // Green transport tracking
      if (greenMethods.includes(event.transportMethod)) {
        greenEvents++;
      }

      // Daily trends
      const date = event.timestamp.split('T')[0];
      const daily = dailyMap.get(date) || { events: 0, carbon: 0 };
      daily.events++;
      daily.carbon += event.carbonFootprintKg;
      dailyMap.set(date, daily);
    }

    const dailyTrends = Array.from(dailyMap.entries())
      .map(([date, data]) => ({ date, ...data }))
      .sort((a, b) => a.date.localeCompare(b.date))
      .slice(-30); // Last 30 days

    return {
      totalEvents: events.length,
      totalDistanceKm: Math.round(totalDistance * 100) / 100,
      totalCarbonKg: Math.round(totalCarbon * 100) / 100,
      avgCarbonPerEvent: events.length > 0 ? Math.round(totalCarbon / events.length * 100) / 100 : 0,
      avgDistancePerEvent: events.length > 0 ? Math.round(totalDistance / events.length * 100) / 100 : 0,
      greenTransportPercentage: events.length > 0 ? Math.round(greenEvents / events.length * 100) : 0,
      methodDistribution: methodCounts,
      dailyTrends
    };
  }

  /**
   * Analyze patterns by user
   */
  private analyzeUserPatterns(events: TransportEvent[]): void {
    const userEvents = new Map<string, TransportEvent[]>();

    for (const event of events) {
      // Group by sender and receiver
      const senderEvents = userEvents.get(event.senderId) || [];
      senderEvents.push(event);
      userEvents.set(event.senderId, senderEvents);

      if (event.senderId !== event.receiverId) {
        const receiverEvents = userEvents.get(event.receiverId) || [];
        receiverEvents.push(event);
        userEvents.set(event.receiverId, receiverEvents);
      }
    }

    for (const [userId, userEventList] of userEvents) {
      this.userAnalytics.set(userId, this.analyzeUser(userId, userEventList));
    }
  }

  /**
   * Analyze a single user's transport patterns
   */
  private analyzeUser(userId: string, events: TransportEvent[]): TransportAnalysis {
    const methodBreakdown: Record<TransportMethod, { count: number; distance: number; carbon: number }> = {} as any;
    const eventTypeBreakdown: Record<TransportEventType, number> = {} as any;

    let totalDistance = 0;
    let totalCarbon = 0;

    for (const event of events) {
      totalDistance += event.distanceKm;
      totalCarbon += event.carbonFootprintKg;

      // Method breakdown
      if (!methodBreakdown[event.transportMethod]) {
        methodBreakdown[event.transportMethod] = { count: 0, distance: 0, carbon: 0 };
      }
      methodBreakdown[event.transportMethod].count++;
      methodBreakdown[event.transportMethod].distance += event.distanceKm;
      methodBreakdown[event.transportMethod].carbon += event.carbonFootprintKg;

      // Event type breakdown
      eventTypeBreakdown[event.eventType] = (eventTypeBreakdown[event.eventType] || 0) + 1;
    }

    // Find most used method
    let mostUsedMethod: TransportMethod = 'walking';
    let maxCount = 0;
    for (const [method, data] of Object.entries(methodBreakdown)) {
      if (data.count > maxCount) {
        maxCount = data.count;
        mostUsedMethod = method as TransportMethod;
      }
    }

    // Calculate efficiency rating
    const carbonPerKm = totalDistance > 0 ? totalCarbon / totalDistance : 0;
    let efficiency: TransportAnalysis['efficiency'];
    if (carbonPerKm < 0.01) efficiency = 'excellent';
    else if (carbonPerKm < 0.05) efficiency = 'good';
    else if (carbonPerKm < 0.1) efficiency = 'average';
    else efficiency = 'poor';

    // Generate recommendations
    const recommendations = this.generateRecommendations(methodBreakdown, carbonPerKm, events);

    return {
      userId,
      totalEvents: events.length,
      totalDistanceKm: Math.round(totalDistance * 100) / 100,
      totalCarbonKg: Math.round(totalCarbon * 100) / 100,
      carbonPerKm: Math.round(carbonPerKm * 1000) / 1000,
      mostUsedMethod,
      methodBreakdown,
      eventTypeBreakdown,
      efficiency,
      recommendations
    };
  }

  /**
   * Generate personalized recommendations
   */
  private generateRecommendations(
    methodBreakdown: Record<TransportMethod, { count: number; distance: number; carbon: number }>,
    carbonPerKm: number,
    events: TransportEvent[]
  ): string[] {
    const recommendations: string[] = [];

    // High-carbon transport suggestions
    if (methodBreakdown['gasoline_vehicle']?.count > 5) {
      recommendations.push('Consider switching to electric vehicle for short-distance transport');
    }

    if (methodBreakdown['air_freight']?.count > 0) {
      recommendations.push('Air freight has 50x the carbon footprint of rail - consider alternatives');
    }

    if (methodBreakdown['refrigerated_truck']?.count > 3) {
      recommendations.push('Batch refrigerated shipments together to reduce trips');
    }

    // Distance-based suggestions
    const avgDistance = events.length > 0
      ? events.reduce((sum, e) => sum + e.distanceKm, 0) / events.length
      : 0;

    if (avgDistance < 5 && !methodBreakdown['bicycle'] && !methodBreakdown['walking']) {
      recommendations.push('Short distances detected - bicycle or walking would eliminate carbon impact');
    }

    // General efficiency
    if (carbonPerKm > 0.1) {
      recommendations.push('Overall carbon efficiency is low - prioritize green transport methods');
    }

    return recommendations.slice(0, 5); // Max 5 recommendations
  }

  /**
   * Detect inefficient transport patterns
   */
  private detectInefficiencies(events: TransportEvent[]): TransportPattern[] {
    const patterns: TransportPattern[] = [];

    // Group events by plant/batch for journey analysis
    const journeys = new Map<string, TransportEvent[]>();

    for (const event of events) {
      // Use a simplified grouping
      const key = event.id.split('-')[0];
      const journey = journeys.get(key) || [];
      journey.push(event);
      journeys.set(key, journey);
    }

    // Check for excessive handling
    for (const [key, journey] of journeys) {
      if (journey.length > 5) {
        patterns.push({
          type: 'excessive_handling',
          description: `${journey.length} transport events detected - consider streamlining logistics`,
          affectedEvents: journey.map(e => e.id),
          potentialSavingsKg: journey.reduce((sum, e) => sum + e.carbonFootprintKg * 0.2, 0),
          severity: journey.length > 10 ? 'high' : 'medium'
        });
      }
    }

    // Check for high-carbon single events
    const highCarbonEvents = events.filter(e => e.carbonFootprintKg > 10);
    for (const event of highCarbonEvents) {
      const alternativeCarbon = CARBON_FACTORS['rail'] * event.distanceKm * 5; // Estimate 5kg cargo
      const savings = event.carbonFootprintKg - alternativeCarbon;

      if (savings > 5) {
        patterns.push({
          type: 'high_carbon',
          description: `High carbon event using ${event.transportMethod} - alternative transport could save ${savings.toFixed(1)}kg CO2`,
          affectedEvents: [event.id],
          potentialSavingsKg: savings,
          severity: savings > 20 ? 'high' : 'medium'
        });
      }
    }

    // Check for cold chain breaks (temperature-sensitive transport)
    const coldChainEvents = events.filter(e =>
      e.transportMethod === 'refrigerated_truck' ||
      (e as any).temperatureControlled === true
    );

    // Simple check: refrigerated followed by non-refrigerated
    for (let i = 0; i < coldChainEvents.length - 1; i++) {
      const current = coldChainEvents[i];
      const next = events.find(e =>
        new Date(e.timestamp) > new Date(current.timestamp) &&
        e.transportMethod !== 'refrigerated_truck'
      );

      if (next) {
        patterns.push({
          type: 'cold_chain_break',
          description: 'Potential cold chain break detected - verify temperature maintenance',
          affectedEvents: [current.id, next.id],
          potentialSavingsKg: 0, // Savings in spoilage, not carbon
          severity: 'medium'
        });
        break; // Only report once
      }
    }

    return patterns;
  }

  /**
   * Check for achievement milestones
   */
  private checkMilestones(): void {
    if (!this.networkStats) return;

    // Carbon milestones
    const carbonMilestones = [100, 500, 1000, 5000, 10000];
    for (const milestone of carbonMilestones) {
      if (this.networkStats.totalCarbonKg > milestone * 0.95 &&
        this.networkStats.totalCarbonKg < milestone * 1.05) {
        this.createAlert('info', `Approaching ${milestone}kg CO2 Network Total`,
          `Network has recorded ${this.networkStats.totalCarbonKg.toFixed(1)}kg total carbon footprint`,
          { relatedEntityType: 'network' }
        );
      }
    }

    // Green transport milestones
    if (this.networkStats.greenTransportPercentage >= 75 &&
      this.networkStats.totalEvents > 100) {
      this.createAlert('info', 'Green Transport Achievement',
        `${this.networkStats.greenTransportPercentage}% of transport uses green methods!`,
        { relatedEntityType: 'network' }
      );
    }
  }

  /**
   * Get user analysis
   */
  getUserAnalysis(userId: string): TransportAnalysis | null {
    return this.userAnalytics.get(userId) || null;
  }

  /**
   * Get network statistics
   */
  getNetworkStats(): NetworkTransportStats | null {
    return this.networkStats;
  }

  /**
   * Get detected patterns
   */
  getPatterns(): TransportPattern[] {
    return this.detectedPatterns;
  }

  /**
   * Calculate carbon savings vs conventional
   */
  calculateSavingsVsConventional(): {
    localGreenCarbon: number;
    conventionalCarbon: number;
    savedKg: number;
    savedPercentage: number;
  } {
    if (!this.networkStats) {
      return { localGreenCarbon: 0, conventionalCarbon: 0, savedKg: 0, savedPercentage: 0 };
    }

    // Conventional: assume 1500 miles avg, 0.2 kg CO2 per mile
    const conventionalCarbon = this.networkStats.totalEvents * 1500 * 1.6 * 0.2;
    const savedKg = Math.max(0, conventionalCarbon - this.networkStats.totalCarbonKg);
    const savedPercentage = conventionalCarbon > 0
      ? Math.round((1 - this.networkStats.totalCarbonKg / conventionalCarbon) * 100)
      : 0;

    return {
      localGreenCarbon: this.networkStats.totalCarbonKg,
      conventionalCarbon: Math.round(conventionalCarbon * 100) / 100,
      savedKg: Math.round(savedKg * 100) / 100,
      savedPercentage
    };
  }
}

// Singleton instance
let transportAgentInstance: TransportTrackerAgent | null = null;

export function getTransportTrackerAgent(): TransportTrackerAgent {
  if (!transportAgentInstance) {
    transportAgentInstance = new TransportTrackerAgent();
  }
  return transportAgentInstance;
}
