/**
 * SustainabilityAgent
 * Monitors and reports on environmental impact across the network
 *
 * Responsibilities:
 * - Calculate network-wide carbon footprint
 * - Track food miles reduction vs conventional
 * - Monitor water usage in vertical farms
 * - Generate sustainability reports
 * - Identify improvement opportunities
 */

import { BaseAgent } from './BaseAgent';
import { AgentConfig, AgentTask, SustainabilityReport } from './types';
import { getTransportChain } from '../transport/tracker';
import { getBlockchain } from '../blockchain/manager';

interface CarbonMetrics {
  totalEmissionsKg: number;
  emissionsPerKgProduce: number;
  savedVsConventionalKg: number;
  percentageReduction: number;
  byTransportMethod: Record<string, number>;
  byEventType: Record<string, number>;
  trend: 'improving' | 'stable' | 'worsening';
}

interface FoodMilesMetrics {
  totalMiles: number;
  avgMilesPerDelivery: number;
  localDeliveryPercent: number; // < 50km
  regionalDeliveryPercent: number; // 50-200km
  longDistancePercent: number; // > 200km
  conventionalComparison: number; // avg miles saved
}

interface WaterMetrics {
  totalUsageLiters: number;
  verticalFarmUsage: number;
  traditionalUsage: number;
  savedLiters: number;
  recyclingRate: number;
  efficiencyScore: number;
}

interface WasteMetrics {
  totalWasteKg: number;
  spoilageKg: number;
  compostedKg: number;
  wasteReductionPercent: number;
  spoilageRate: number;
}

interface SustainabilityScore {
  overall: number;
  carbon: number;
  water: number;
  waste: number;
  localFood: number;
  biodiversity: number;
}

interface ImprovementOpportunity {
  id: string;
  category: 'carbon' | 'water' | 'waste' | 'transport' | 'energy';
  title: string;
  description: string;
  potentialImpact: string;
  difficulty: 'easy' | 'moderate' | 'challenging';
  estimatedSavings: { value: number; unit: string };
  priority: 'low' | 'medium' | 'high';
}

export class SustainabilityAgent extends BaseAgent {
  private carbonMetrics: CarbonMetrics | null = null;
  private foodMilesMetrics: FoodMilesMetrics | null = null;
  private waterMetrics: WaterMetrics | null = null;
  private wasteMetrics: WasteMetrics | null = null;
  private sustainabilityScore: SustainabilityScore | null = null;
  private opportunities: ImprovementOpportunity[] = [];
  private historicalScores: { date: string; score: number }[] = [];

  constructor() {
    const config: AgentConfig = {
      id: 'sustainability-agent',
      name: 'Sustainability Agent',
      description: 'Monitors environmental impact and sustainability metrics',
      enabled: true,
      intervalMs: 300000, // Run every 5 minutes
      priority: 'medium',
      maxRetries: 3,
      timeoutMs: 60000
    };
    super(config);
  }

  /**
   * Main execution cycle
   */
  async runOnce(): Promise<AgentTask | null> {
    // Calculate all metrics
    this.carbonMetrics = this.calculateCarbonMetrics();
    this.foodMilesMetrics = this.calculateFoodMilesMetrics();
    this.waterMetrics = this.calculateWaterMetrics();
    this.wasteMetrics = this.calculateWasteMetrics();

    // Calculate overall sustainability score
    this.sustainabilityScore = this.calculateSustainabilityScore();

    // Track historical scores
    this.historicalScores.push({
      date: new Date().toISOString(),
      score: this.sustainabilityScore.overall
    });
    if (this.historicalScores.length > 365) {
      this.historicalScores = this.historicalScores.slice(-365);
    }

    // Identify improvement opportunities
    this.opportunities = this.identifyOpportunities();

    // Generate alerts for concerning metrics
    this.checkMetricAlerts();

    // Generate milestone alerts
    this.checkMilestones();

    return this.createTaskResult('sustainability_analysis', 'completed', {
      overallScore: this.sustainabilityScore.overall,
      carbonSavedKg: this.carbonMetrics.savedVsConventionalKg,
      foodMilesSaved: this.foodMilesMetrics?.conventionalComparison || 0,
      opportunitiesIdentified: this.opportunities.length
    });
  }

  /**
   * Calculate carbon metrics
   */
  private calculateCarbonMetrics(): CarbonMetrics {
    const transportChain = getTransportChain();
    const events = transportChain.chain.slice(1).map(b => b.transportEvent);

    let totalEmissions = 0;
    let totalWeightKg = 0;
    const byMethod: Record<string, number> = {};
    const byEventType: Record<string, number> = {};

    for (const event of events) {
      totalEmissions += event.carbonFootprintKg;
      totalWeightKg += 5; // Estimate avg weight

      byMethod[event.transportMethod] = (byMethod[event.transportMethod] || 0) + event.carbonFootprintKg;
      byEventType[event.eventType] = (byEventType[event.eventType] || 0) + event.carbonFootprintKg;
    }

    // Conventional comparison: 2.5 kg CO2 per kg produce avg
    const conventionalEmissions = totalWeightKg * 2.5;
    const saved = Math.max(0, conventionalEmissions - totalEmissions);

    // Determine trend
    const recentScores = this.historicalScores.slice(-10);
    let trend: 'improving' | 'stable' | 'worsening' = 'stable';

    if (recentScores.length >= 5) {
      const firstHalf = recentScores.slice(0, 5).reduce((s, e) => s + e.score, 0) / 5;
      const secondHalf = recentScores.slice(-5).reduce((s, e) => s + e.score, 0) / 5;
      if (secondHalf > firstHalf + 2) trend = 'improving';
      else if (secondHalf < firstHalf - 2) trend = 'worsening';
    }

    return {
      totalEmissionsKg: Math.round(totalEmissions * 100) / 100,
      emissionsPerKgProduce: totalWeightKg > 0
        ? Math.round((totalEmissions / totalWeightKg) * 1000) / 1000
        : 0,
      savedVsConventionalKg: Math.round(saved * 100) / 100,
      percentageReduction: conventionalEmissions > 0
        ? Math.round((1 - totalEmissions / conventionalEmissions) * 100)
        : 0,
      byTransportMethod: byMethod,
      byEventType,
      trend
    };
  }

  /**
   * Calculate food miles metrics
   */
  private calculateFoodMilesMetrics(): FoodMilesMetrics {
    const transportChain = getTransportChain();
    const events = transportChain.chain.slice(1).map(b => b.transportEvent);

    let totalMiles = 0;
    let localCount = 0;
    let regionalCount = 0;
    let longDistanceCount = 0;

    for (const event of events) {
      const km = event.distanceKm;
      totalMiles += km;

      if (km < 50) localCount++;
      else if (km < 200) regionalCount++;
      else longDistanceCount++;
    }

    const totalDeliveries = events.length;

    // Conventional avg: 1500 miles per item
    const conventionalMiles = totalDeliveries * 1500;

    return {
      totalMiles: Math.round(totalMiles),
      avgMilesPerDelivery: totalDeliveries > 0
        ? Math.round(totalMiles / totalDeliveries)
        : 0,
      localDeliveryPercent: totalDeliveries > 0
        ? Math.round((localCount / totalDeliveries) * 100)
        : 0,
      regionalDeliveryPercent: totalDeliveries > 0
        ? Math.round((regionalCount / totalDeliveries) * 100)
        : 0,
      longDistancePercent: totalDeliveries > 0
        ? Math.round((longDistanceCount / totalDeliveries) * 100)
        : 0,
      conventionalComparison: Math.round(conventionalMiles - totalMiles)
    };
  }

  /**
   * Calculate water metrics (simulated for demo)
   */
  private calculateWaterMetrics(): WaterMetrics {
    const blockchain = getBlockchain();
    const plantCount = blockchain.getChain().length - 1;

    // Simulate water usage based on plant count
    // Vertical farms use ~10% of traditional water
    const traditionalUsagePerPlant = 500; // liters
    const verticalFarmUsagePerPlant = 50; // liters

    const verticalFarmRatio = 0.3; // 30% in vertical farms
    const verticalFarmPlants = Math.floor(plantCount * verticalFarmRatio);
    const traditionalPlants = plantCount - verticalFarmPlants;

    const verticalUsage = verticalFarmPlants * verticalFarmUsagePerPlant;
    const traditionalUsage = traditionalPlants * traditionalUsagePerPlant;
    const totalUsage = verticalUsage + traditionalUsage;

    const conventionalUsage = plantCount * traditionalUsagePerPlant;
    const saved = conventionalUsage - totalUsage;

    return {
      totalUsageLiters: totalUsage,
      verticalFarmUsage: verticalUsage,
      traditionalUsage: traditionalUsage,
      savedLiters: Math.max(0, saved),
      recyclingRate: 85, // 85% water recycling in vertical farms
      efficiencyScore: Math.round((saved / conventionalUsage) * 100)
    };
  }

  /**
   * Calculate waste metrics (simulated for demo)
   */
  private calculateWasteMetrics(): WasteMetrics {
    const blockchain = getBlockchain();
    const plants = blockchain.getChain().slice(1);

    const deceasedPlants = plants.filter(p => p.plant.status === 'deceased').length;
    const totalPlants = plants.length;

    // Conventional spoilage: 30-40%
    const conventionalSpoilageRate = 0.35;
    const localSpoilageRate = totalPlants > 0
      ? deceasedPlants / totalPlants
      : 0;

    const totalProduceKg = totalPlants * 2; // Estimate 2kg per plant
    const spoilageKg = totalProduceKg * localSpoilageRate;
    const compostedKg = spoilageKg * 0.8; // 80% composted

    return {
      totalWasteKg: Math.round(spoilageKg * 10) / 10,
      spoilageKg: Math.round(spoilageKg * 10) / 10,
      compostedKg: Math.round(compostedKg * 10) / 10,
      wasteReductionPercent: Math.round((conventionalSpoilageRate - localSpoilageRate) / conventionalSpoilageRate * 100),
      spoilageRate: Math.round(localSpoilageRate * 100)
    };
  }

  /**
   * Calculate overall sustainability score
   */
  private calculateSustainabilityScore(): SustainabilityScore {
    const carbon = this.carbonMetrics
      ? Math.min(100, Math.max(0, this.carbonMetrics.percentageReduction + 20))
      : 50;

    const water = this.waterMetrics
      ? Math.min(100, this.waterMetrics.efficiencyScore + 30)
      : 50;

    const waste = this.wasteMetrics
      ? Math.min(100, 100 - this.wasteMetrics.spoilageRate * 2)
      : 50;

    const localFood = this.foodMilesMetrics
      ? Math.min(100, this.foodMilesMetrics.localDeliveryPercent + this.foodMilesMetrics.regionalDeliveryPercent)
      : 50;

    // Biodiversity: based on plant variety
    const blockchain = getBlockchain();
    const plants = blockchain.getChain().slice(1);
    const uniqueSpecies = new Set(plants.map(p => p.plant.commonName)).size;
    const biodiversity = Math.min(100, 30 + uniqueSpecies * 5);

    const overall = Math.round(
      (carbon * 0.25 + water * 0.2 + waste * 0.15 + localFood * 0.25 + biodiversity * 0.15)
    );

    return {
      overall,
      carbon: Math.round(carbon),
      water: Math.round(water),
      waste: Math.round(waste),
      localFood: Math.round(localFood),
      biodiversity: Math.round(biodiversity)
    };
  }

  /**
   * Identify improvement opportunities
   */
  private identifyOpportunities(): ImprovementOpportunity[] {
    const opportunities: ImprovementOpportunity[] = [];

    // Carbon opportunities
    if (this.carbonMetrics) {
      if (this.carbonMetrics.byTransportMethod['gasoline_vehicle'] > 10) {
        opportunities.push({
          id: `opp-${Date.now()}-ev`,
          category: 'transport',
          title: 'Switch to Electric Vehicles',
          description: 'Replace gasoline vehicles with EVs for local deliveries',
          potentialImpact: 'Reduce transport emissions by 60-80%',
          difficulty: 'moderate',
          estimatedSavings: {
            value: this.carbonMetrics.byTransportMethod['gasoline_vehicle'] * 0.7,
            unit: 'kg CO2'
          },
          priority: 'high'
        });
      }

      if (this.carbonMetrics.byTransportMethod['air_freight'] > 0) {
        opportunities.push({
          id: `opp-${Date.now()}-air`,
          category: 'transport',
          title: 'Eliminate Air Freight',
          description: 'Replace air freight with rail or local sourcing',
          potentialImpact: 'Eliminate highest-carbon transport method',
          difficulty: 'challenging',
          estimatedSavings: {
            value: this.carbonMetrics.byTransportMethod['air_freight'],
            unit: 'kg CO2'
          },
          priority: 'high'
        });
      }
    }

    // Food miles opportunities
    if (this.foodMilesMetrics && this.foodMilesMetrics.longDistancePercent > 10) {
      opportunities.push({
        id: `opp-${Date.now()}-local`,
        category: 'transport',
        title: 'Increase Local Sourcing',
        description: 'Partner with more local growers to reduce food miles',
        potentialImpact: `Reduce ${this.foodMilesMetrics.longDistancePercent}% long-distance deliveries`,
        difficulty: 'moderate',
        estimatedSavings: {
          value: Math.round(this.foodMilesMetrics.totalMiles * 0.3),
          unit: 'miles'
        },
        priority: 'medium'
      });
    }

    // Water opportunities
    if (this.waterMetrics && this.waterMetrics.recyclingRate < 90) {
      opportunities.push({
        id: `opp-${Date.now()}-water`,
        category: 'water',
        title: 'Improve Water Recycling',
        description: 'Upgrade water recycling systems in vertical farms',
        potentialImpact: 'Increase water recycling from 85% to 95%',
        difficulty: 'moderate',
        estimatedSavings: {
          value: Math.round(this.waterMetrics.totalUsageLiters * 0.1),
          unit: 'liters'
        },
        priority: 'medium'
      });
    }

    // Waste opportunities
    if (this.wasteMetrics && this.wasteMetrics.spoilageRate > 10) {
      opportunities.push({
        id: `opp-${Date.now()}-waste`,
        category: 'waste',
        title: 'Reduce Spoilage Rate',
        description: 'Implement better cold chain and demand forecasting',
        potentialImpact: 'Reduce spoilage from ' + this.wasteMetrics.spoilageRate + '% to 5%',
        difficulty: 'moderate',
        estimatedSavings: {
          value: Math.round(this.wasteMetrics.spoilageKg * 0.5),
          unit: 'kg produce'
        },
        priority: 'high'
      });
    }

    return opportunities.sort((a, b) =>
      a.priority === 'high' ? -1 : b.priority === 'high' ? 1 : 0
    );
  }

  /**
   * Check metric alerts
   */
  private checkMetricAlerts(): void {
    if (this.carbonMetrics && this.carbonMetrics.trend === 'worsening') {
      this.createAlert('warning', 'Carbon Footprint Increasing',
        'Network carbon emissions trending upward over the past week',
        { actionRequired: 'Review transport methods and route efficiency' }
      );
    }

    if (this.wasteMetrics && this.wasteMetrics.spoilageRate > 15) {
      this.createAlert('warning', 'High Spoilage Rate',
        `Current spoilage rate of ${this.wasteMetrics.spoilageRate}% exceeds target of 10%`,
        { actionRequired: 'Improve cold chain or demand matching' }
      );
    }

    if (this.foodMilesMetrics && this.foodMilesMetrics.localDeliveryPercent < 30) {
      this.createAlert('info', 'Low Local Delivery Rate',
        `Only ${this.foodMilesMetrics.localDeliveryPercent}% of deliveries are local (<50km)`,
        { actionRequired: 'Expand local grower network' }
      );
    }
  }

  /**
   * Check for milestone achievements
   */
  private checkMilestones(): void {
    const milestones = [
      { carbon: 100, message: '100 kg CO2 saved!' },
      { carbon: 500, message: '500 kg CO2 saved!' },
      { carbon: 1000, message: '1 tonne CO2 saved!' },
      { carbon: 5000, message: '5 tonnes CO2 saved!' }
    ];

    if (this.carbonMetrics) {
      for (const milestone of milestones) {
        const saved = this.carbonMetrics.savedVsConventionalKg;
        if (saved >= milestone.carbon * 0.98 && saved <= milestone.carbon * 1.02) {
          this.createAlert('info', 'Sustainability Milestone',
            milestone.message,
            { relatedEntityType: 'network' }
          );
        }
      }
    }
  }

  /**
   * Generate sustainability report
   */
  generateReport(): SustainabilityReport {
    const now = new Date();
    const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);

    return {
      periodStart: weekAgo.toISOString(),
      periodEnd: now.toISOString(),
      totalCarbonSavedKg: this.carbonMetrics?.savedVsConventionalKg || 0,
      totalFoodMilesSaved: this.foodMilesMetrics?.conventionalComparison || 0,
      localProductionPercentage: this.foodMilesMetrics?.localDeliveryPercent || 0,
      wasteReductionPercentage: this.wasteMetrics?.wasteReductionPercent || 0,
      waterSavedLiters: this.waterMetrics?.savedLiters || 0,
      recommendations: this.opportunities.slice(0, 3).map(o => o.title)
    };
  }

  /**
   * Get carbon metrics
   */
  getCarbonMetrics(): CarbonMetrics | null {
    return this.carbonMetrics;
  }

  /**
   * Get food miles metrics
   */
  getFoodMilesMetrics(): FoodMilesMetrics | null {
    return this.foodMilesMetrics;
  }

  /**
   * Get water metrics
   */
  getWaterMetrics(): WaterMetrics | null {
    return this.waterMetrics;
  }

  /**
   * Get waste metrics
   */
  getWasteMetrics(): WasteMetrics | null {
    return this.wasteMetrics;
  }

  /**
   * Get sustainability score
   */
  getSustainabilityScore(): SustainabilityScore | null {
    return this.sustainabilityScore;
  }

  /**
   * Get improvement opportunities
   */
  getOpportunities(): ImprovementOpportunity[] {
    return this.opportunities;
  }

  /**
   * Get historical scores
   */
  getHistoricalScores(): { date: string; score: number }[] {
    return this.historicalScores;
  }
}

// Singleton instance
let sustainabilityAgentInstance: SustainabilityAgent | null = null;

export function getSustainabilityAgent(): SustainabilityAgent {
  if (!sustainabilityAgentInstance) {
    sustainabilityAgentInstance = new SustainabilityAgent();
  }
  return sustainabilityAgentInstance;
}
