/**
 * AI Service for generating intelligent task suggestions
 * Uses OpenAI API to analyze street conditions and suggest maintenance tasks
 */

const axios = require("axios");
const logger = require("../utils/logger");

class AIService {
  constructor() {
    this.apiKey = process.env.OPENAI_API_KEY;
    this.model = process.env.OPENAI_MODEL || "gpt-3.5-turbo";
    this.apiUrl = "https://api.openai.com/v1/chat/completions";
    this.isConfigured = !!this.apiKey;
    
    if (!this.isConfigured) {
      logger.warn("OpenAI API key not configured. AI service will return mock data.");
    } else {
      logger.info("AI Service initialized", { model: this.model });
    }
  }

  /**
   * Generate task suggestions for a street
   * @param {Object} options - Options for generating suggestions
   * @param {string} options.streetName - Name of the street
   * @param {Object} options.location - Location coordinates {type: 'Point', coordinates: [lng, lat]}
   * @param {Array} options.pastTasks - Array of past task descriptions
   * @param {Object} options.weather - Weather conditions (optional)
   * @param {Array} options.communityPriorities - Community priorities (optional)
   * @param {number} options.numberOfSuggestions - Number of suggestions to generate (default: 5)
   * @returns {Promise<Array>} Array of task suggestions
   */
  async generateTaskSuggestions(options = {}) {
    const {
      streetName,
      location,
      pastTasks = [],
      weather = null,
      communityPriorities = [],
      numberOfSuggestions = 5
    } = options;

    // If API is not configured, return mock suggestions with warning
    if (!this.isConfigured) {
      logger.warn("Returning mock suggestions - OpenAI API not configured");
      return this._getMockSuggestions(streetName, numberOfSuggestions);
    }

    try {
      // Build context-aware prompt
      const prompt = this._buildPrompt({
        streetName,
        location,
        pastTasks,
        weather,
        communityPriorities,
        numberOfSuggestions
      });

      logger.debug("Generating AI task suggestions", { 
        streetName, 
        model: this.model,
        pastTasksCount: pastTasks.length 
      });

      // Call OpenAI API
      const response = await axios.post(
        this.apiUrl,
        {
          model: this.model,
          messages: [
            {
              role: "system",
              content: "You are a helpful assistant that generates practical street maintenance task suggestions for community volunteers. Focus on actionable, safe, and impactful tasks that can be completed by regular citizens."
            },
            {
              role: "user",
              content: prompt
            }
          ],
          temperature: 0.7,
          max_tokens: 1000
        },
        {
          headers: {
            "Content-Type": "application/json",
            "Authorization": `Bearer ${this.apiKey}`
          },
          timeout: 10000 // 10 second timeout
        }
      );

      // Parse the response
      const suggestions = this._parseOpenAIResponse(response.data, streetName);
      
      logger.info("AI task suggestions generated successfully", { 
        streetName, 
        count: suggestions.length 
      });

      return suggestions;

    } catch (error) {
      logger.error("Error generating AI task suggestions", error, { 
        streetName,
        errorType: error.response?.status || error.code 
      });

      // Fallback to mock suggestions on error
      logger.info("Falling back to mock suggestions due to API error");
      return this._getMockSuggestions(streetName, numberOfSuggestions);
    }
  }

  /**
   * Build a context-aware prompt for OpenAI
   * @private
   */
  _buildPrompt(options) {
    const {
      streetName,
      location,
      pastTasks,
      weather,
      communityPriorities,
      numberOfSuggestions
    } = options;

    let prompt = `Generate ${numberOfSuggestions} practical street maintenance task suggestions for "${streetName}".`;

    // Add location context if available
    if (location && location.coordinates) {
      const [lng, lat] = location.coordinates;
      prompt += `\nLocation: Latitude ${lat.toFixed(4)}, Longitude ${lng.toFixed(4)}`;
    }

    // Add past tasks context
    if (pastTasks.length > 0) {
      prompt += `\n\nRecent tasks completed on this street:`;
      pastTasks.slice(0, 10).forEach((task, index) => {
        prompt += `\n${index + 1}. ${task}`;
      });
      prompt += `\n\nAvoid suggesting tasks that are too similar to recently completed ones.`;
    }

    // Add weather context
    if (weather) {
      prompt += `\n\nCurrent weather conditions: ${weather.description || weather.condition}`;
      if (weather.temperature) {
        prompt += ` (${weather.temperature}°F)`;
      }
      prompt += `\nSuggest tasks appropriate for these weather conditions.`;
    }

    // Add community priorities
    if (communityPriorities.length > 0) {
      prompt += `\n\nCommunity priorities: ${communityPriorities.join(", ")}`;
      prompt += `\nPrioritize suggestions that align with these community goals.`;
    }

    // Add formatting instructions
    prompt += `\n\nFormat your response as a JSON array of objects, each with:
- "description": A clear, actionable task description (2-8 words)
- "details": A brief explanation of why this task is important (1 sentence)
- "estimatedTime": Estimated time to complete in minutes (number)
- "difficulty": Either "easy", "moderate", or "hard"
- "priority": Either "low", "medium", or "high"

Example format:
[
  {
    "description": "Remove litter from sidewalk",
    "details": "Improves neighborhood appearance and prevents storm drain blockage.",
    "estimatedTime": 30,
    "difficulty": "easy",
    "priority": "medium"
  }
]

Ensure tasks are safe for volunteers without specialized equipment.`;

    return prompt;
  }

  /**
   * Parse OpenAI API response into task suggestions
   * @private
   */
  _parseOpenAIResponse(data, streetName) {
    try {
      const content = data.choices[0]?.message?.content;
      
      if (!content) {
        throw new Error("No content in OpenAI response");
      }

      // Extract JSON from response (handle markdown code blocks)
      let jsonStr = content.trim();
      
      // Remove markdown code block syntax if present
      if (jsonStr.startsWith("```")) {
        jsonStr = jsonStr.replace(/```json?\n?/g, "").replace(/```\n?/g, "");
      }

      const suggestions = JSON.parse(jsonStr);

      // Validate and format suggestions
      if (!Array.isArray(suggestions)) {
        throw new Error("Response is not an array");
      }

      return suggestions.map(suggestion => ({
        street: streetName,
        description: suggestion.description || "Maintenance task",
        details: suggestion.details || "",
        estimatedTime: suggestion.estimatedTime || 60,
        difficulty: suggestion.difficulty || "moderate",
        priority: suggestion.priority || "medium",
        source: "ai"
      }));

    } catch (error) {
      logger.error("Error parsing OpenAI response", error, { 
        response: data.choices[0]?.message?.content?.substring(0, 200) 
      });
      throw new Error("Failed to parse AI response");
    }
  }

  /**
   * Get mock task suggestions as fallback
   * @private
   */
  _getMockSuggestions(streetName, count = 5) {
    const mockPool = [
      {
        description: "Remove litter from sidewalk",
        details: "Improves neighborhood appearance and prevents storm drain blockage.",
        estimatedTime: 30,
        difficulty: "easy",
        priority: "medium"
      },
      {
        description: "Clear leaves from gutters",
        details: "Prevents water accumulation and potential flooding during rain.",
        estimatedTime: 45,
        difficulty: "easy",
        priority: "high"
      },
      {
        description: "Trim overgrown vegetation",
        details: "Maintains clear walkways and improves visibility for pedestrians.",
        estimatedTime: 60,
        difficulty: "moderate",
        priority: "medium"
      },
      {
        description: "Paint over graffiti",
        details: "Restores aesthetic appeal and discourages vandalism.",
        estimatedTime: 90,
        difficulty: "moderate",
        priority: "high"
      },
      {
        description: "Report broken street lights",
        details: "Enhances safety and security for residents during nighttime.",
        estimatedTime: 15,
        difficulty: "easy",
        priority: "high"
      },
      {
        description: "Clean storm drains",
        details: "Ensures proper drainage and prevents flooding.",
        estimatedTime: 40,
        difficulty: "moderate",
        priority: "medium"
      },
      {
        description: "Repair minor sidewalk cracks",
        details: "Prevents trip hazards and further deterioration.",
        estimatedTime: 120,
        difficulty: "hard",
        priority: "low"
      },
      {
        description: "Water street trees",
        details: "Maintains urban canopy and provides shade for the community.",
        estimatedTime: 25,
        difficulty: "easy",
        priority: "low"
      }
    ];

    // Randomly select suggestions from the pool
    const shuffled = mockPool.sort(() => 0.5 - Math.random());
    const selected = shuffled.slice(0, Math.min(count, mockPool.length));

    return selected.map(suggestion => ({
      street: streetName || "Selected Street",
      ...suggestion,
      source: "mock"
    }));
  }

  /**
   * Check if AI service is properly configured
   * @returns {boolean}
   */
  isAvailable() {
    return this.isConfigured;
  }

  /**
   * Get service status information
   * @returns {Object}
   */
  getStatus() {
    return {
      configured: this.isConfigured,
      model: this.isConfigured ? this.model : null,
      status: this.isConfigured ? "active" : "mock_mode"
    };
  }
}

// Export singleton instance
module.exports = new AIService();
