/**
 * @ai-summary Integration tests for community stations API
 * @ai-context Tests full API workflow with database
 */

import { FastifyInstance } from 'fastify';
import { Pool } from 'pg';
import { buildApp } from '../../../../app';
import { pool as pgPool } from '../../../../core/config/database';

describe('Community Stations API Integration Tests', () => {
  let app: FastifyInstance;
  let pool: Pool;

  const testUserId = 'auth0|test-user-123';
  const testAdminId = 'auth0|test-admin-123';

  const mockStationData = {
    name: 'Test Gas Station',
    address: '123 Main St',
    city: 'Springfield',
    state: 'IL',
    zipCode: '62701',
    latitude: 39.7817,
    longitude: -89.6501,
    brand: 'Shell',
    has93Octane: true,
    has93OctaneEthanolFree: false,
    price93: 3.50,
    notes: 'Great service'
  };

  beforeAll(async () => {
    pool = pgPool;
    app = await buildApp();

    // Clean up test data
    await pool.query('DELETE FROM community_stations WHERE submitted_by IN ($1, $2)', [testUserId, testAdminId]);
  });

  afterAll(async () => {
    // Clean up test data
    await pool.query('DELETE FROM community_stations WHERE submitted_by IN ($1, $2)', [testUserId, testAdminId]);
    await app.close();
  });

  describe('POST /api/stations/community - Submit station', () => {
    it('should submit a new community station', async () => {
      const response = await app.inject({
        method: 'POST',
        url: '/api/stations/community',
        headers: {
          authorization: `Bearer ${testUserId}`
        },
        payload: mockStationData
      });

      expect(response.statusCode).toBe(201);
      const body = JSON.parse(response.body);
      expect(body.id).toBeDefined();
      expect(body.status).toBe('pending');
      expect(body.submittedBy).toBe(testUserId);
      expect(body.name).toBe(mockStationData.name);
    });

    it('should validate required fields', async () => {
      const incompleteData = {
        name: 'Test Station',
        address: '123 Main St'
        // Missing latitude and longitude
      };

      const response = await app.inject({
        method: 'POST',
        url: '/api/stations/community',
        headers: {
          authorization: `Bearer ${testUserId}`
        },
        payload: incompleteData
      });

      expect(response.statusCode).toBe(400);
      const body = JSON.parse(response.body);
      expect(body.error).toBe('Validation error');
    });

    it('should validate latitude bounds', async () => {
      const invalidData = {
        ...mockStationData,
        latitude: 91 // Invalid: must be between -90 and 90
      };

      const response = await app.inject({
        method: 'POST',
        url: '/api/stations/community',
        headers: {
          authorization: `Bearer ${testUserId}`
        },
        payload: invalidData
      });

      expect(response.statusCode).toBe(400);
      const body = JSON.parse(response.body);
      expect(body.error).toBe('Validation error');
    });

    it('should require authentication', async () => {
      const response = await app.inject({
        method: 'POST',
        url: '/api/stations/community',
        payload: mockStationData
      });

      expect(response.statusCode).toBe(401);
    });
  });

  describe('GET /api/stations/community/mine - Get user submissions', () => {
    let submittedStationId: string;

    beforeAll(async () => {
      // Submit a test station
      const response = await app.inject({
        method: 'POST',
        url: '/api/stations/community',
        headers: {
          authorization: `Bearer ${testUserId}`
        },
        payload: mockStationData
      });

      const body = JSON.parse(response.body);
      submittedStationId = body.id;
    });

    it('should retrieve user submissions', async () => {
      const response = await app.inject({
        method: 'GET',
        url: '/api/stations/community/mine',
        headers: {
          authorization: `Bearer ${testUserId}`
        }
      });

      expect(response.statusCode).toBe(200);
      const body = JSON.parse(response.body);
      expect(body.total).toBeGreaterThan(0);
      expect(Array.isArray(body.stations)).toBe(true);
      expect(body.stations.some((s: any) => s.id === submittedStationId)).toBe(true);
    });

    it('should support pagination', async () => {
      const response = await app.inject({
        method: 'GET',
        url: '/api/stations/community/mine?limit=10&offset=0',
        headers: {
          authorization: `Bearer ${testUserId}`
        }
      });

      expect(response.statusCode).toBe(200);
      const body = JSON.parse(response.body);
      expect(body.stations).toBeDefined();
      expect(body.total).toBeDefined();
    });

    it('should require authentication', async () => {
      const response = await app.inject({
        method: 'GET',
        url: '/api/stations/community/mine'
      });

      expect(response.statusCode).toBe(401);
    });
  });

  describe('DELETE /api/stations/community/:id - Withdraw submission', () => {
    let pendingStationId: string;

    beforeAll(async () => {
      // Submit a test station
      const response = await app.inject({
        method: 'POST',
        url: '/api/stations/community',
        headers: {
          authorization: `Bearer ${testUserId}`
        },
        payload: {
          ...mockStationData,
          name: 'Pending Station to Withdraw'
        }
      });

      const body = JSON.parse(response.body);
      pendingStationId = body.id;
    });

    it('should allow user to withdraw own pending submission', async () => {
      const response = await app.inject({
        method: 'DELETE',
        url: `/api/stations/community/${pendingStationId}`,
        headers: {
          authorization: `Bearer ${testUserId}`
        }
      });

      expect(response.statusCode).toBe(204);

      // Verify it's deleted
      const checkResponse = await app.inject({
        method: 'GET',
        url: '/api/stations/community/mine',
        headers: {
          authorization: `Bearer ${testUserId}`
        }
      });

      const body = JSON.parse(checkResponse.body);
      expect(body.stations.some((s: any) => s.id === pendingStationId)).toBe(false);
    });

    it('should reject withdrawal of non-existent station', async () => {
      const response = await app.inject({
        method: 'DELETE',
        url: '/api/stations/community/invalid-id',
        headers: {
          authorization: `Bearer ${testUserId}`
        }
      });

      expect(response.statusCode).toBe(400);
    });

    it('should require authentication', async () => {
      const response = await app.inject({
        method: 'DELETE',
        url: `/api/stations/community/${pendingStationId}`
      });

      expect(response.statusCode).toBe(401);
    });
  });

  describe('GET /api/stations/community/approved - Get approved stations', () => {
    it('should retrieve approved stations', async () => {
      const response = await app.inject({
        method: 'GET',
        url: '/api/stations/community/approved',
        headers: {
          authorization: `Bearer ${testUserId}`
        }
      });

      expect(response.statusCode).toBe(200);
      const body = JSON.parse(response.body);
      expect(body.total).toBeDefined();
      expect(Array.isArray(body.stations)).toBe(true);
    });

    it('should return only approved stations', async () => {
      const response = await app.inject({
        method: 'GET',
        url: '/api/stations/community/approved',
        headers: {
          authorization: `Bearer ${testUserId}`
        }
      });

      const body = JSON.parse(response.body);
      body.stations.forEach((station: any) => {
        expect(station.status).toBe('approved');
      });
    });

    it('should support pagination', async () => {
      const response = await app.inject({
        method: 'GET',
        url: '/api/stations/community/approved?limit=10&offset=0',
        headers: {
          authorization: `Bearer ${testUserId}`
        }
      });

      expect(response.statusCode).toBe(200);
    });
  });

  describe('POST /api/stations/community/nearby - Find nearby stations', () => {
    it('should find nearby approved stations', async () => {
      const response = await app.inject({
        method: 'POST',
        url: '/api/stations/community/nearby',
        headers: {
          authorization: `Bearer ${testUserId}`
        },
        payload: {
          latitude: 39.7817,
          longitude: -89.6501,
          radiusKm: 50
        }
      });

      expect(response.statusCode).toBe(200);
      const body = JSON.parse(response.body);
      expect(Array.isArray(body.stations)).toBe(true);
    });

    it('should validate location coordinates', async () => {
      const response = await app.inject({
        method: 'POST',
        url: '/api/stations/community/nearby',
        headers: {
          authorization: `Bearer ${testUserId}`
        },
        payload: {
          latitude: 91, // Invalid
          longitude: -89.6501,
          radiusKm: 50
        }
      });

      expect(response.statusCode).toBe(400);
    });

    it('should validate radius', async () => {
      const response = await app.inject({
        method: 'POST',
        url: '/api/stations/community/nearby',
        headers: {
          authorization: `Bearer ${testUserId}`
        },
        payload: {
          latitude: 39.7817,
          longitude: -89.6501,
          radiusKm: 1000 // Too large
        }
      });

      expect(response.statusCode).toBe(400);
    });
  });

  describe('Admin endpoints', () => {
    it('should require admin role for admin endpoints', async () => {
      const response = await app.inject({
        method: 'GET',
        url: '/api/admin/community-stations',
        headers: {
          authorization: `Bearer ${testUserId}`
        }
      });

      expect(response.statusCode).toBe(403);
    });

    // Note: Full admin endpoint testing would require proper admin role setup
    // These tests verify the routes are protected
  });
});
