import request from 'supertest';
import app from '../app';

// Force JSON store mode for tests
process.env.USE_JSON_STORE = 'true';

const API_KEY = 'test-api-key-for-development';

describe('API Endpoints', () => {
  describe('Health Check', () => {
    it('GET /health should return ok status', async () => {
      const res = await request(app).get('/health');

      expect(res.status).toBe(200);
      expect(res.body).toHaveProperty('status', 'ok');
      expect(res.body).toHaveProperty('timestamp');
    });
  });

  describe('Authentication', () => {
    it('should reject requests without API key', async () => {
      const res = await request(app).get('/api/v1/sports');

      expect(res.status).toBe(401);
      expect(res.body).toHaveProperty('error');
    });

    it('should reject requests with invalid API key', async () => {
      const res = await request(app)
        .get('/api/v1/sports')
        .set('X-API-Key', 'invalid-key');

      expect(res.status).toBe(401);
    });

    it('should accept requests with valid API key', async () => {
      const res = await request(app)
        .get('/api/v1/sports')
        .set('X-API-Key', API_KEY);

      expect(res.status).toBe(200);
    });
  });

  describe('GET /api/v1/sports', () => {
    it('should return all sports', async () => {
      const res = await request(app)
        .get('/api/v1/sports')
        .set('X-API-Key', API_KEY);

      expect(res.status).toBe(200);
      expect(res.body).toHaveProperty('sports');
      expect(Array.isArray(res.body.sports)).toBe(true);
    });

    it('should filter by isActive=true', async () => {
      const res = await request(app)
        .get('/api/v1/sports?isActive=true')
        .set('X-API-Key', API_KEY);

      expect(res.status).toBe(200);
      expect(res.body.sports.every((s: any) => s.isActive === true)).toBe(true);
    });

    it('should filter by isActive=false', async () => {
      const res = await request(app)
        .get('/api/v1/sports?isActive=false')
        .set('X-API-Key', API_KEY);

      expect(res.status).toBe(200);
      expect(res.body.sports.every((s: any) => s.isActive === false)).toBe(true);
    });
  });

  describe('GET /api/v1/sports/:sportId/leagues', () => {
    it('should return leagues for a valid sport ID', async () => {
      // First get a sport
      const sportsRes = await request(app)
        .get('/api/v1/sports')
        .set('X-API-Key', API_KEY);

      if (sportsRes.body.sports.length > 0) {
        const sportId = sportsRes.body.sports[0].id;
        const res = await request(app)
          .get(`/api/v1/sports/${sportId}/leagues`)
          .set('X-API-Key', API_KEY);

        expect(res.status).toBe(200);
        expect(res.body).toHaveProperty('leagues');
        expect(Array.isArray(res.body.leagues)).toBe(true);
      }
    });

    it('should return 404 for non-existent sport ID', async () => {
      const res = await request(app)
        .get('/api/v1/sports/99999/leagues')
        .set('X-API-Key', API_KEY);

      expect(res.status).toBe(404);
    });

    it('should reject non-numeric sport ID', async () => {
      const res = await request(app)
        .get('/api/v1/sports/invalid/leagues')
        .set('X-API-Key', API_KEY);

      expect(res.status).toBe(400);
    });
  });

  describe('GET /api/v1/leagues/:leagueId/participants', () => {
    it('should return participants for a valid league ID', async () => {
      // Get a sport first
      const sportsRes = await request(app)
        .get('/api/v1/sports')
        .set('X-API-Key', API_KEY);

      if (sportsRes.body.sports.length > 0) {
        const sportId = sportsRes.body.sports[0].id;
        const leaguesRes = await request(app)
          .get(`/api/v1/sports/${sportId}/leagues`)
          .set('X-API-Key', API_KEY);

        if (leaguesRes.body.leagues.length > 0) {
          const leagueId = leaguesRes.body.leagues[0].id;
          const res = await request(app)
            .get(`/api/v1/leagues/${leagueId}/participants`)
            .set('X-API-Key', API_KEY);

          expect(res.status).toBe(200);
          expect(res.body).toHaveProperty('participants');
          expect(Array.isArray(res.body.participants)).toBe(true);
        }
      }
    });

    it('should return 404 for non-existent league ID', async () => {
      const res = await request(app)
        .get('/api/v1/leagues/99999/participants')
        .set('X-API-Key', API_KEY);

      expect(res.status).toBe(404);
    });

    it('should filter by participant type', async () => {
      const sportsRes = await request(app)
        .get('/api/v1/sports')
        .set('X-API-Key', API_KEY);

      if (sportsRes.body.sports.length > 0) {
        const sportId = sportsRes.body.sports[0].id;
        const leaguesRes = await request(app)
          .get(`/api/v1/sports/${sportId}/leagues`)
          .set('X-API-Key', API_KEY);

        if (leaguesRes.body.leagues.length > 0) {
          const leagueId = leaguesRes.body.leagues[0].id;
          const res = await request(app)
            .get(`/api/v1/leagues/${leagueId}/participants?type=TEAM`)
            .set('X-API-Key', API_KEY);

          expect(res.status).toBe(200);
          expect(res.body.participants.every((p: any) => p.participantType === 'TEAM')).toBe(true);
        }
      }
    });
  });

  describe('GET /api/v1/leagues/:leagueId/widget-types', () => {
    it('should return widget types for a valid league ID', async () => {
      // Get a league first
      const sportsRes = await request(app)
        .get('/api/v1/sports')
        .set('X-API-Key', API_KEY);

      if (sportsRes.body.sports.length > 0) {
        const sportId = sportsRes.body.sports[0].id;
        const leaguesRes = await request(app)
          .get(`/api/v1/sports/${sportId}/leagues`)
          .set('X-API-Key', API_KEY);

        if (leaguesRes.body.leagues.length > 0) {
          const leagueId = leaguesRes.body.leagues[0].id;
          const res = await request(app)
            .get(`/api/v1/leagues/${leagueId}/widget-types`)
            .set('X-API-Key', API_KEY);

          expect(res.status).toBe(200);
          expect(res.body).toHaveProperty('widgetTypes');
          expect(Array.isArray(res.body.widgetTypes)).toBe(true);
          // All widget types should belong to the requested league
          expect(res.body.widgetTypes.every((w: any) => w.leagueId === leagueId)).toBe(true);
        }
      }
    });

    it('should return 404 for non-existent league ID', async () => {
      const res = await request(app)
        .get('/api/v1/leagues/99999/widget-types')
        .set('X-API-Key', API_KEY);

      expect(res.status).toBe(404);
    });

    it('should reject non-numeric league ID', async () => {
      const res = await request(app)
        .get('/api/v1/leagues/invalid/widget-types')
        .set('X-API-Key', API_KEY);

      expect(res.status).toBe(400);
    });

    it('should filter by isActive', async () => {
      const sportsRes = await request(app)
        .get('/api/v1/sports')
        .set('X-API-Key', API_KEY);

      if (sportsRes.body.sports.length > 0) {
        const sportId = sportsRes.body.sports[0].id;
        const leaguesRes = await request(app)
          .get(`/api/v1/sports/${sportId}/leagues`)
          .set('X-API-Key', API_KEY);

        if (leaguesRes.body.leagues.length > 0) {
          const leagueId = leaguesRes.body.leagues[0].id;
          const res = await request(app)
            .get(`/api/v1/leagues/${leagueId}/widget-types?isActive=true`)
            .set('X-API-Key', API_KEY);

          expect(res.status).toBe(200);
          expect(res.body.widgetTypes.every((w: any) => w.isActive === true)).toBe(true);
        }
      }
    });
  });

  describe('GET /api/v1/templates', () => {
    it('should return all templates with embed codes', async () => {
      const res = await request(app)
        .get('/api/v1/templates')
        .set('X-API-Key', API_KEY);

      expect(res.status).toBe(200);
      expect(res.body).toHaveProperty('templates');
      expect(Array.isArray(res.body.templates)).toBe(true);

      if (res.body.templates.length > 0) {
        expect(res.body.templates[0]).toHaveProperty('embedCodeLight');
        expect(res.body.templates[0]).toHaveProperty('embedCodeDark');
      }
    });

    it('should filter by sportId', async () => {
      const sportsRes = await request(app)
        .get('/api/v1/sports')
        .set('X-API-Key', API_KEY);

      if (sportsRes.body.sports.length > 0) {
        const sportId = sportsRes.body.sports[0].id;
        const res = await request(app)
          .get(`/api/v1/templates?sportId=${sportId}`)
          .set('X-API-Key', API_KEY);

        expect(res.status).toBe(200);
        expect(res.body.templates.every((t: any) => t.sportId === sportId)).toBe(true);
      }
    });

    it('should filter by featured', async () => {
      const res = await request(app)
        .get('/api/v1/templates?featured=true')
        .set('X-API-Key', API_KEY);

      expect(res.status).toBe(200);
      expect(res.body.templates.every((t: any) => t.featured === true)).toBe(true);
    });

    it('should filter by isActive', async () => {
      const res = await request(app)
        .get('/api/v1/templates?isActive=true')
        .set('X-API-Key', API_KEY);

      expect(res.status).toBe(200);
      expect(res.body.templates.every((t: any) => t.isActive === true)).toBe(true);
    });

    it('should support multiple filters', async () => {
      const sportsRes = await request(app)
        .get('/api/v1/sports')
        .set('X-API-Key', API_KEY);

      if (sportsRes.body.sports.length > 0) {
        const sportId = sportsRes.body.sports[0].id;
        const res = await request(app)
          .get(`/api/v1/templates?sportId=${sportId}&isActive=true`)
          .set('X-API-Key', API_KEY);

        expect(res.status).toBe(200);
        expect(
          res.body.templates.every((t: any) => t.sportId === sportId && t.isActive === true)
        ).toBe(true);
      }
    });
  });

  describe('API Documentation', () => {
    it('GET /docs should return HTML documentation', async () => {
      const res = await request(app).get('/docs');

      expect(res.status).toBe(200);
      expect(res.text).toContain('<!DOCTYPE html>');
      expect(res.text).toContain('redoc');
    });

    it('GET /openapi.json should return OpenAPI spec', async () => {
      const res = await request(app).get('/openapi.json');

      expect(res.status).toBe(200);
      expect(res.body).toHaveProperty('openapi');
      expect(res.body).toHaveProperty('info');
      expect(res.body).toHaveProperty('paths');
    });
  });
});
