const axios = require('axios');

class RepresentAPIService {
  constructor() {
    this.baseURL = process.env.REPRESENT_API_BASE || 'https://represent.opennorth.ca';
    this.rateLimit = parseInt(process.env.REPRESENT_API_RATE_LIMIT) || 60;
    this.lastRequestTime = 0;
    this.requestCount = 0;
    this.resetTime = Date.now() + 60000; // Reset every minute
  }

  async checkRateLimit() {
    const now = Date.now();
    
    // Reset counter if a minute has passed
    if (now > this.resetTime) {
      this.requestCount = 0;
      this.resetTime = now + 60000;
    }
    
    // Check if we're at the rate limit
    if (this.requestCount >= this.rateLimit) {
      const waitTime = this.resetTime - now;
      throw new Error(`Rate limit exceeded. Please wait ${Math.ceil(waitTime / 1000)} seconds.`);
    }
    
    this.requestCount++;
    this.lastRequestTime = now;
  }

  async makeRequest(endpoint) {
    await this.checkRateLimit();
    
    try {
      const response = await axios.get(`${this.baseURL}${endpoint}`, {
        timeout: 10000,
        headers: {
          'User-Agent': 'Alberta-Influence-Campaign-Tool/1.0'
        }
      });
      
      return response.data;
    } catch (error) {
      if (error.response) {
        throw new Error(`API Error: ${error.response.status} - ${error.response.statusText}`);
      } else if (error.request) {
        throw new Error('Network error: Unable to reach Represent API');
      } else {
        throw new Error(`Request error: ${error.message}`);
      }
    }
  }

  async testConnection() {
    try {
      const data = await this.makeRequest('/boundary-sets/?limit=1');
      return {
        success: true,
        message: 'Successfully connected to Represent API',
        sampleData: data
      };
    } catch (error) {
      return {
        success: false,
        message: 'Failed to connect to Represent API',
        error: error.message
      };
    }
  }

  async getRepresentativesByPostalCode(postalCode) {
    const formattedPostalCode = postalCode.replace(/\s/g, '').toUpperCase();
    
    // Validate Alberta postal code (should start with T)
    if (!formattedPostalCode.startsWith('T')) {
      throw new Error('This tool is designed for Alberta postal codes only (starting with T)');
    }
    
    try {
      const endpoint = `/postcodes/${formattedPostalCode}/`;
      console.log(`Making Represent API request to: ${this.baseURL}${endpoint}`);
      const data = await this.makeRequest(endpoint);
      
      console.log('Represent API Response:', JSON.stringify(data, null, 2));
      console.log(`Representatives concordance count: ${data.representatives_concordance?.length || 0}`);
      console.log(`Representatives centroid count: ${data.representatives_centroid?.length || 0}`);
      
      return {
        postalCode: formattedPostalCode,
        city: data.city,
        province: data.province,
        centroid: data.centroid,
        representatives_concordance: data.representatives_concordance || [],
        representatives_centroid: data.representatives_centroid || [],
        boundaries_concordance: data.boundaries_concordance || [],
        boundaries_centroid: data.boundaries_centroid || []
      };
    } catch (error) {
      console.error(`Represent API error for ${formattedPostalCode}:`, error.message);
      throw new Error(`Failed to fetch data for postal code ${formattedPostalCode}: ${error.message}`);
    }
  }

  async getRepresentativeDetails(representativeUrl) {
    try {
      // Extract the path from the URL
      const urlPath = representativeUrl.replace(this.baseURL, '');
      const data = await this.makeRequest(urlPath);
      return data;
    } catch (error) {
      throw new Error(`Failed to fetch representative details: ${error.message}`);
    }
  }

  async getBoundaryDetails(boundaryUrl) {
    try {
      // Extract the path from the URL
      const urlPath = boundaryUrl.replace(this.baseURL, '');
      const data = await this.makeRequest(urlPath);
      return data;
    } catch (error) {
      throw new Error(`Failed to fetch boundary details: ${error.message}`);
    }
  }

  async searchRepresentatives(filters = {}) {
    try {
      const queryParams = new URLSearchParams();
      
      // Add filters as query parameters
      Object.keys(filters).forEach(key => {
        if (filters[key]) {
          queryParams.append(key, filters[key]);
        }
      });
      
      const endpoint = `/representatives/?${queryParams.toString()}`;
      const data = await this.makeRequest(endpoint);
      return data;
    } catch (error) {
      throw new Error(`Failed to search representatives: ${error.message}`);
    }
  }
}

module.exports = new RepresentAPIService();