/**
 * Seed-to-Seed Lifecycle Integration Tests
 * Tests complete lifecycle from seed acquisition to seed saving
 */

import { TransportChain, setTransportChain } from '../../lib/transport/tracker';
import {
  SeedAcquisitionEvent,
  PlantingEvent,
  GrowingTransportEvent,
  HarvestEvent,
  SeedSavingEvent,
  SeedSharingEvent,
  TransportLocation,
} from '../../lib/transport/types';

describe('Seed-to-Seed Lifecycle', () => {
  let chain: TransportChain;

  beforeEach(() => {
    chain = new TransportChain(1); // Low difficulty for faster tests
    setTransportChain(chain);
  });

  describe('Complete Lifecycle', () => {
    it('should track complete lifecycle from seed acquisition to seed saving', () => {
      const seedBatchId = 'lifecycle-batch-001';
      const plantIds = ['plant-lifecycle-001', 'plant-lifecycle-002'];
      const newSeedBatchId = 'lifecycle-batch-002';

      // Step 1: Seed Acquisition
      const seedAcquisition: SeedAcquisitionEvent = {
        id: 'lifecycle-seed-001',
        timestamp: new Date().toISOString(),
        eventType: 'seed_acquisition',
        fromLocation: createLocation('seed_bank', 'Heritage Seed Bank'),
        toLocation: createLocation('greenhouse', 'Local Grower Greenhouse'),
        distanceKm: 50,
        durationMinutes: 60,
        transportMethod: 'electric_vehicle',
        carbonFootprintKg: 0,
        senderId: 'seed-bank-heritage',
        receiverId: 'grower-local-001',
        status: 'verified',
        seedBatchId,
        sourceType: 'seed_bank',
        species: 'Solanum lycopersicum',
        variety: 'Brandywine',
        quantity: 50,
        quantityUnit: 'seeds',
        generation: 3,
        germinationRate: 92,
        certifications: ['heirloom', 'organic'],
      };

      const block1 = chain.recordEvent(seedAcquisition);
      expect(block1.transportEvent.eventType).toBe('seed_acquisition');

      // Step 2: Planting
      const planting: PlantingEvent = {
        id: 'lifecycle-planting-001',
        timestamp: new Date(Date.now() + 1000).toISOString(),
        eventType: 'planting',
        fromLocation: createLocation('greenhouse', 'Local Grower Greenhouse'),
        toLocation: createLocation('greenhouse', 'Local Grower Greenhouse'),
        distanceKm: 0,
        durationMinutes: 30,
        transportMethod: 'walking',
        carbonFootprintKg: 0,
        senderId: 'grower-local-001',
        receiverId: 'grower-local-001',
        status: 'verified',
        seedBatchId,
        plantIds,
        plantingMethod: 'indoor_start',
        quantityPlanted: 2,
        growingEnvironment: 'greenhouse',
        expectedHarvestDate: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toISOString(),
      };

      const block2 = chain.recordEvent(planting);
      expect(block2.transportEvent.eventType).toBe('planting');

      // Step 3: Growing Transport (transplant to outdoor garden)
      const transplant: GrowingTransportEvent = {
        id: 'lifecycle-transplant-001',
        timestamp: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(), // 30 days later
        eventType: 'growing_transport',
        fromLocation: createLocation('greenhouse', 'Local Grower Greenhouse'),
        toLocation: createLocation('farm', 'Local Community Garden'),
        distanceKm: 2,
        durationMinutes: 20,
        transportMethod: 'bicycle',
        carbonFootprintKg: 0,
        senderId: 'grower-local-001',
        receiverId: 'grower-local-001',
        status: 'verified',
        plantIds,
        reason: 'transplant',
        plantStage: 'vegetative',
        handlingMethod: 'potted',
        rootDisturbance: 'minimal',
        acclimatizationRequired: true,
        acclimatizationDays: 7,
      };

      const block3 = chain.recordEvent(transplant);
      expect(block3.transportEvent.eventType).toBe('growing_transport');

      // Step 4: Harvest
      const harvest: HarvestEvent = {
        id: 'lifecycle-harvest-001',
        timestamp: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toISOString(), // 90 days after planting
        eventType: 'harvest',
        fromLocation: createLocation('farm', 'Local Community Garden'),
        toLocation: createLocation('warehouse', 'Local Co-op Distribution'),
        distanceKm: 5,
        durationMinutes: 15,
        transportMethod: 'electric_vehicle',
        carbonFootprintKg: 0,
        senderId: 'grower-local-001',
        receiverId: 'coop-distribution',
        status: 'verified',
        plantIds,
        harvestBatchId: 'harvest-lifecycle-001',
        harvestType: 'full',
        produceType: 'Brandywine Tomatoes',
        grossWeight: 8,
        netWeight: 7.5,
        weightUnit: 'kg',
        qualityGrade: 'A',
        packagingType: 'sustainable_crates',
        temperatureRequired: { min: 12, max: 18, optimal: 15, unit: 'celsius' },
        shelfLifeHours: 168,
        seedsSaved: true,
        seedBatchIdCreated: newSeedBatchId,
      };

      const block4 = chain.recordEvent(harvest);
      expect(block4.transportEvent.eventType).toBe('harvest');

      // Step 5: Seed Saving
      const seedSaving: SeedSavingEvent = {
        id: 'lifecycle-seed-saving-001',
        timestamp: new Date(Date.now() + 95 * 24 * 60 * 60 * 1000).toISOString(),
        eventType: 'seed_saving',
        fromLocation: createLocation('farm', 'Local Community Garden'),
        toLocation: createLocation('seed_bank', 'Grower Home Seed Storage'),
        distanceKm: 1,
        durationMinutes: 10,
        transportMethod: 'walking',
        carbonFootprintKg: 0,
        senderId: 'grower-local-001',
        receiverId: 'grower-local-001',
        status: 'verified',
        parentPlantIds: plantIds,
        newSeedBatchId,
        collectionMethod: 'fermentation',
        seedCount: 200,
        germinationRate: 88,
        storageConditions: {
          temperature: 10,
          humidity: 30,
          lightExposure: 'dark',
          containerType: 'jar',
          desiccant: true,
          estimatedViability: 5,
        },
        storageLocationId: 'grower-home-storage',
        newGenerationNumber: 4,
        geneticNotes: 'Selected from best performing plants',
        availableForSharing: true,
        sharingTerms: 'trade',
      };

      const block5 = chain.recordEvent(seedSaving);
      expect(block5.transportEvent.eventType).toBe('seed_saving');

      // Verify complete journey
      const journey1 = chain.getPlantJourney(plantIds[0]);
      expect(journey1).not.toBeNull();
      expect(journey1?.events.length).toBe(4); // planting, transplant, harvest, seed_saving
      expect(journey1?.currentStage).toBe('seed_saving');
      expect(journey1?.descendantSeedBatches).toContain(newSeedBatchId);

      // Verify chain integrity
      expect(chain.isChainValid()).toBe(true);

      // Verify carbon tracking
      expect(block5.cumulativeCarbonKg).toBeGreaterThanOrEqual(0);
      expect(block5.cumulativeFoodMiles).toBe(
        seedAcquisition.distanceKm +
        planting.distanceKm +
        transplant.distanceKm +
        harvest.distanceKm +
        seedSaving.distanceKm
      );
    });

    it('should track multiple generations', () => {
      // Generation 1 seeds
      const gen1Batch = 'gen1-batch';
      const gen1Plants = ['gen1-plant-001'];
      const gen2Batch = 'gen2-batch';
      const gen2Plants = ['gen2-plant-001'];
      const gen3Batch = 'gen3-batch';

      // Gen 1: Acquire, Plant, Harvest with seed saving
      chain.recordEvent(createSeedAcquisition(gen1Batch, 1));
      chain.recordEvent(createPlanting(gen1Batch, gen1Plants));
      chain.recordEvent(createHarvest(gen1Plants, gen2Batch));
      chain.recordEvent(createSeedSaving(gen1Plants, gen2Batch, 2));

      // Gen 2: Plant saved seeds, Harvest with seed saving
      chain.recordEvent(createSeedAcquisition(gen2Batch, 2, gen1Plants));
      chain.recordEvent(createPlanting(gen2Batch, gen2Plants));
      chain.recordEvent(createHarvest(gen2Plants, gen3Batch));
      chain.recordEvent(createSeedSaving(gen2Plants, gen3Batch, 3));

      // Verify chain
      expect(chain.isChainValid()).toBe(true);
      expect(chain.chain.length).toBe(9); // 1 genesis + 8 events

      // Verify lineage
      const journey = chain.getPlantJourney('gen2-plant-001');
      expect(journey?.generation).toBe(2);
    });
  });

  describe('Seed Sharing', () => {
    it('should track seed sharing between growers', () => {
      const originalBatch = 'original-batch';
      const sharedQuantity = 25;

      // Save seeds
      const seedSaving: SeedSavingEvent = {
        id: 'share-seed-saving',
        timestamp: new Date().toISOString(),
        eventType: 'seed_saving',
        fromLocation: createLocation('farm', 'Grower A Farm'),
        toLocation: createLocation('seed_bank', 'Grower A Storage'),
        distanceKm: 0,
        durationMinutes: 30,
        transportMethod: 'walking',
        carbonFootprintKg: 0,
        senderId: 'grower-a',
        receiverId: 'grower-a',
        status: 'verified',
        parentPlantIds: ['parent-001'],
        newSeedBatchId: originalBatch,
        collectionMethod: 'dry_seed',
        seedCount: 100,
        storageConditions: {
          temperature: 10,
          humidity: 30,
          lightExposure: 'dark',
          containerType: 'envelope',
          desiccant: true,
          estimatedViability: 4,
        },
        storageLocationId: 'grower-a-storage',
        newGenerationNumber: 2,
        availableForSharing: true,
        sharingTerms: 'trade',
      };

      chain.recordEvent(seedSaving);

      // Share seeds
      const seedSharing: SeedSharingEvent = {
        id: 'share-event-001',
        timestamp: new Date(Date.now() + 1000).toISOString(),
        eventType: 'seed_sharing',
        fromLocation: createLocation('seed_bank', 'Grower A Storage'),
        toLocation: createLocation('greenhouse', 'Grower B Greenhouse'),
        distanceKm: 10,
        durationMinutes: 20,
        transportMethod: 'bicycle',
        carbonFootprintKg: 0,
        senderId: 'grower-a',
        receiverId: 'grower-b',
        status: 'verified',
        seedBatchId: originalBatch,
        quantityShared: sharedQuantity,
        quantityUnit: 'seeds',
        sharingType: 'trade',
        tradeDetails: 'Traded for basil seeds',
        recipientAgreement: true,
        growingCommitment: 'Will grow and save seeds',
        reportBackRequired: true,
      };

      const block = chain.recordEvent(seedSharing);

      expect(block.transportEvent.eventType).toBe('seed_sharing');
      expect((block.transportEvent as SeedSharingEvent).quantityShared).toBe(sharedQuantity);
    });
  });

  describe('Environmental Impact Across Lifecycle', () => {
    it('should calculate cumulative environmental impact', () => {
      const userId = 'eco-grower';

      // Record full lifecycle with the same user
      const events = [
        { distanceKm: 50, method: 'electric_vehicle' as const },
        { distanceKm: 0, method: 'walking' as const },
        { distanceKm: 5, method: 'bicycle' as const },
        { distanceKm: 10, method: 'electric_truck' as const },
        { distanceKm: 1, method: 'walking' as const },
      ];

      let totalDistance = 0;
      events.forEach((event, i) => {
        chain.recordEvent({
          id: `eco-event-${i}`,
          timestamp: new Date(Date.now() + i * 1000).toISOString(),
          eventType: 'seed_acquisition',
          fromLocation: createLocation('farm', 'Location A'),
          toLocation: createLocation('farm', 'Location B'),
          distanceKm: event.distanceKm,
          durationMinutes: 30,
          transportMethod: event.method,
          carbonFootprintKg: 0,
          senderId: userId,
          receiverId: userId,
          status: 'verified',
          seedBatchId: `batch-${i}`,
          sourceType: 'previous_harvest',
          species: 'Test',
          quantity: 10,
          quantityUnit: 'seeds',
          generation: 1,
        } as SeedAcquisitionEvent);
        totalDistance += event.distanceKm;
      });

      const impact = chain.getEnvironmentalImpact(userId);

      expect(impact.totalFoodMiles).toBe(totalDistance);
      expect(impact.comparisonToConventional.milesSaved).toBeGreaterThan(0);
    });
  });

  describe('QR Code Traceability', () => {
    it('should generate traceable QR codes at each stage', () => {
      const plantId = 'qr-trace-plant';
      const batchId = 'qr-trace-batch';

      // Record seed acquisition
      chain.recordEvent({
        id: 'qr-seed',
        timestamp: new Date().toISOString(),
        eventType: 'seed_acquisition',
        fromLocation: createLocation('seed_bank', 'Bank'),
        toLocation: createLocation('greenhouse', 'Greenhouse'),
        distanceKm: 10,
        durationMinutes: 20,
        transportMethod: 'bicycle',
        carbonFootprintKg: 0,
        senderId: 'seller',
        receiverId: 'buyer',
        status: 'verified',
        seedBatchId: batchId,
        sourceType: 'seed_bank',
        species: 'Test',
        quantity: 10,
        quantityUnit: 'seeds',
        generation: 1,
      } as SeedAcquisitionEvent);

      // Record planting
      chain.recordEvent({
        id: 'qr-planting',
        timestamp: new Date(Date.now() + 1000).toISOString(),
        eventType: 'planting',
        fromLocation: createLocation('greenhouse', 'Greenhouse'),
        toLocation: createLocation('greenhouse', 'Greenhouse'),
        distanceKm: 0,
        durationMinutes: 10,
        transportMethod: 'walking',
        carbonFootprintKg: 0,
        senderId: 'buyer',
        receiverId: 'buyer',
        status: 'verified',
        seedBatchId: batchId,
        plantIds: [plantId],
        plantingMethod: 'indoor_start',
        quantityPlanted: 1,
        growingEnvironment: 'greenhouse',
      } as PlantingEvent);

      // Generate QR for plant
      const plantQR = chain.generateQRData(plantId, undefined);
      expect(plantQR.plantId).toBe(plantId);
      expect(plantQR.lastEventType).toBe('planting');

      // Generate QR for batch
      const batchQR = chain.generateQRData(undefined, batchId);
      expect(batchQR.batchId).toBe(batchId);

      // Both should have valid verification codes
      expect(plantQR.verificationCode).toMatch(/^[A-F0-9]{8}$/);
      expect(batchQR.verificationCode).toMatch(/^[A-F0-9]{8}$/);
    });
  });
});

// Helper functions
function createLocation(type: string, name: string): TransportLocation {
  return {
    latitude: 40.7 + Math.random() * 0.1,
    longitude: -74.0 + Math.random() * 0.1,
    locationType: type as any,
    facilityName: name,
  };
}

function createSeedAcquisition(
  batchId: string,
  generation: number,
  parentPlantIds?: string[]
): SeedAcquisitionEvent {
  return {
    id: `seed-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`,
    timestamp: new Date().toISOString(),
    eventType: 'seed_acquisition',
    fromLocation: createLocation('seed_bank', 'Bank'),
    toLocation: createLocation('greenhouse', 'Greenhouse'),
    distanceKm: 10,
    durationMinutes: 20,
    transportMethod: 'electric_vehicle',
    carbonFootprintKg: 0,
    senderId: 'sender',
    receiverId: 'receiver',
    status: 'verified',
    seedBatchId: batchId,
    sourceType: parentPlantIds ? 'previous_harvest' : 'seed_bank',
    species: 'Test Species',
    quantity: 10,
    quantityUnit: 'seeds',
    generation,
    parentPlantIds,
  };
}

function createPlanting(batchId: string, plantIds: string[]): PlantingEvent {
  return {
    id: `planting-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`,
    timestamp: new Date(Date.now() + 100).toISOString(),
    eventType: 'planting',
    fromLocation: createLocation('greenhouse', 'Greenhouse'),
    toLocation: createLocation('greenhouse', 'Greenhouse'),
    distanceKm: 0,
    durationMinutes: 10,
    transportMethod: 'walking',
    carbonFootprintKg: 0,
    senderId: 'grower',
    receiverId: 'grower',
    status: 'verified',
    seedBatchId: batchId,
    plantIds,
    plantingMethod: 'indoor_start',
    quantityPlanted: plantIds.length,
    growingEnvironment: 'greenhouse',
  };
}

function createHarvest(plantIds: string[], newSeedBatchId: string): HarvestEvent {
  return {
    id: `harvest-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`,
    timestamp: new Date(Date.now() + 200).toISOString(),
    eventType: 'harvest',
    fromLocation: createLocation('farm', 'Farm'),
    toLocation: createLocation('warehouse', 'Warehouse'),
    distanceKm: 5,
    durationMinutes: 20,
    transportMethod: 'electric_truck',
    carbonFootprintKg: 0,
    senderId: 'grower',
    receiverId: 'distributor',
    status: 'verified',
    plantIds,
    harvestBatchId: `harvest-batch-${Date.now()}`,
    harvestType: 'full',
    produceType: 'Test Produce',
    grossWeight: 5,
    netWeight: 4.5,
    weightUnit: 'kg',
    packagingType: 'crates',
    temperatureRequired: { min: 10, max: 20, optimal: 15, unit: 'celsius' },
    shelfLifeHours: 168,
    seedsSaved: true,
    seedBatchIdCreated: newSeedBatchId,
  };
}

function createSeedSaving(
  parentPlantIds: string[],
  newSeedBatchId: string,
  generation: number
): SeedSavingEvent {
  return {
    id: `save-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`,
    timestamp: new Date(Date.now() + 300).toISOString(),
    eventType: 'seed_saving',
    fromLocation: createLocation('farm', 'Farm'),
    toLocation: createLocation('seed_bank', 'Storage'),
    distanceKm: 0,
    durationMinutes: 30,
    transportMethod: 'walking',
    carbonFootprintKg: 0,
    senderId: 'grower',
    receiverId: 'grower',
    status: 'verified',
    parentPlantIds,
    newSeedBatchId,
    collectionMethod: 'dry_seed',
    seedCount: 50,
    storageConditions: {
      temperature: 10,
      humidity: 30,
      lightExposure: 'dark',
      containerType: 'envelope',
      desiccant: true,
      estimatedViability: 4,
    },
    storageLocationId: 'grower-storage',
    newGenerationNumber: generation,
    availableForSharing: true,
  };
}
