/**
 * GrowerAdvisoryAgent Tests
 * Tests for the grower advisory and recommendation system
 */

import {
  GrowerAdvisoryAgent,
  getGrowerAdvisoryAgent,
} from '../../../lib/agents/GrowerAdvisoryAgent';

describe('GrowerAdvisoryAgent', () => {
  let agent: GrowerAdvisoryAgent;

  beforeEach(() => {
    agent = new GrowerAdvisoryAgent();
  });

  describe('Initialization', () => {
    it('should create agent with correct configuration', () => {
      expect(agent.config.id).toBe('grower-advisory-agent');
      expect(agent.config.name).toBe('Grower Advisory Agent');
      expect(agent.config.enabled).toBe(true);
      expect(agent.config.priority).toBe('high');
    });

    it('should have correct interval (5 minutes)', () => {
      expect(agent.config.intervalMs).toBe(300000);
    });

    it('should start in idle status', () => {
      expect(agent.status).toBe('idle');
    });

    it('should have empty metrics initially', () => {
      const metrics = agent.getMetrics();
      expect(metrics.tasksCompleted).toBe(0);
      expect(metrics.tasksFailed).toBe(0);
      expect(metrics.errors).toEqual([]);
    });
  });

  describe('Grower Profile Management', () => {
    it('should register a grower profile', () => {
      const profile = createGrowerProfile('grower-1');
      agent.registerGrowerProfile(profile);

      const retrieved = agent.getGrowerProfile('grower-1');
      expect(retrieved).not.toBeNull();
      expect(retrieved?.growerId).toBe('grower-1');
    });

    it('should return null for unknown grower', () => {
      const retrieved = agent.getGrowerProfile('unknown-grower');
      expect(retrieved).toBeNull();
    });

    it('should update existing profile', () => {
      const profile1 = createGrowerProfile('grower-1');
      profile1.experienceLevel = 'beginner';
      agent.registerGrowerProfile(profile1);

      const profile2 = createGrowerProfile('grower-1');
      profile2.experienceLevel = 'expert';
      agent.registerGrowerProfile(profile2);

      const retrieved = agent.getGrowerProfile('grower-1');
      expect(retrieved?.experienceLevel).toBe('expert');
    });
  });

  describe('Recommendations', () => {
    it('should return empty recommendations for unknown grower', () => {
      const recs = agent.getRecommendations('unknown-grower');
      expect(recs).toEqual([]);
    });

    it('should get recommendations after profile registration', () => {
      const profile = createGrowerProfile('grower-1');
      agent.registerGrowerProfile(profile);

      // Recommendations are generated during runOnce
      const recs = agent.getRecommendations('grower-1');
      expect(Array.isArray(recs)).toBe(true);
    });
  });

  describe('Rotation Advice', () => {
    it('should return null for unknown grower', () => {
      const advice = agent.getRotationAdvice('unknown-grower');
      expect(advice).toBeNull();
    });
  });

  describe('Market Opportunities', () => {
    it('should return array of opportunities', () => {
      const opps = agent.getOpportunities();
      expect(Array.isArray(opps)).toBe(true);
    });
  });

  describe('Grower Performance', () => {
    it('should return null for unknown grower', () => {
      const perf = agent.getPerformance('unknown-grower');
      expect(perf).toBeNull();
    });
  });

  describe('Seasonal Alerts', () => {
    it('should return array of seasonal alerts', () => {
      const alerts = agent.getSeasonalAlerts();
      expect(Array.isArray(alerts)).toBe(true);
    });
  });

  describe('Agent Lifecycle', () => {
    it('should start and change status to running', async () => {
      await agent.start();
      expect(agent.status).toBe('running');
      await agent.stop();
    });

    it('should stop and change status to idle', async () => {
      await agent.start();
      await agent.stop();
      expect(agent.status).toBe('idle');
    });

    it('should pause when running', async () => {
      await agent.start();
      agent.pause();
      expect(agent.status).toBe('paused');
      await agent.stop();
    });

    it('should resume after pause', async () => {
      await agent.start();
      agent.pause();
      agent.resume();
      expect(agent.status).toBe('running');
      await agent.stop();
    });
  });

  describe('Singleton', () => {
    it('should return same instance from getGrowerAdvisoryAgent', () => {
      const agent1 = getGrowerAdvisoryAgent();
      const agent2 = getGrowerAdvisoryAgent();
      expect(agent1).toBe(agent2);
    });
  });

  describe('Alerts', () => {
    it('should return alerts array', () => {
      const alerts = agent.getAlerts();
      expect(Array.isArray(alerts)).toBe(true);
    });
  });

  describe('Task Execution', () => {
    it('should execute runOnce successfully', async () => {
      const profile = createGrowerProfile('grower-1');
      agent.registerGrowerProfile(profile);

      const result = await agent.runOnce();

      expect(result).not.toBeNull();
      expect(result?.status).toBe('completed');
      expect(result?.type).toBe('grower_advisory');
    });

    it('should report metrics in task result', async () => {
      const profile = createGrowerProfile('grower-1');
      agent.registerGrowerProfile(profile);

      const result = await agent.runOnce();

      expect(result?.result).toHaveProperty('growersAdvised');
      expect(result?.result).toHaveProperty('recommendationsGenerated');
      expect(result?.result).toHaveProperty('opportunitiesIdentified');
      expect(result?.result).toHaveProperty('alertsGenerated');
    });

    it('should count registered growers', async () => {
      agent.registerGrowerProfile(createGrowerProfile('grower-1'));
      agent.registerGrowerProfile(createGrowerProfile('grower-2'));
      agent.registerGrowerProfile(createGrowerProfile('grower-3'));

      const result = await agent.runOnce();

      expect(result?.result?.growersAdvised).toBe(3);
    });
  });
});

// Helper function to create test grower profiles
function createGrowerProfile(
  growerId: string,
  lat: number = 40.7128,
  lon: number = -74.006
) {
  return {
    growerId,
    growerName: `Test Grower ${growerId}`,
    location: { latitude: lat, longitude: lon },
    availableSpaceSqm: 100,
    specializations: ['lettuce', 'tomato'],
    certifications: ['organic'],
    experienceLevel: 'intermediate' as const,
    preferredCrops: ['lettuce', 'tomato', 'basil'],
    growingHistory: [
      { cropType: 'lettuce', successRate: 85, avgYield: 4.5 },
      { cropType: 'tomato', successRate: 75, avgYield: 8.0 },
    ],
  };
}
