/**
 * AI Configuration Controller - Multi-tenant AI Management
 * Handles AI provider configurations with tenant isolation
 */

const crypto = require('crypto');
const { pool } = require('../config/database');
const { logger } = require('../config/logger');
const axios = require('axios');

class AIConfigController {
  /**
   * Get AI configurations for tenant
   * GET /api/tenant/ai-config/settings
   */
  async getSettings(req, res) {
    let connection;
    try {
      const tenantId = req.user.tenantId;

      connection = await pool.getConnection();

      const [settings] = await connection.execute(
        `SELECT 
          ac.id,
          ac.evolution_instance_id,
          ac.provider,
          ac.model_name,
          ac.persona_name,
          ac.persona_description,
          ac.system_prompt,
          ac.temperature,
          ac.max_tokens,
          ac.active,
          ac.business_hours_start,
          ac.business_hours_end,
          ac.business_days,
          ac.auto_response_enabled,
          ac.response_delay,
          ac.created_at,
          ac.updated_at,
          ei.instance_name,
          ei.phone_number,
          ei.status as instance_status,
          CASE 
            WHEN ac.api_key IS NOT NULL AND ac.api_key != '' THEN 'configured'
            ELSE 'not_configured'
          END as api_key_status
        FROM ai_configurations ac
        LEFT JOIN evolution_instances ei ON ac.evolution_instance_id = ei.id
        WHERE ac.tenant_id = ?
        ORDER BY ei.instance_name ASC, ac.created_at DESC`,
        [tenantId]
      );

      res.json(settings);
    } catch (error) {
      logger.error('Error fetching AI configurations:', error);
      res.status(500).json({ error: 'Error fetching AI configurations' });
    } finally {
      if (connection) connection.release();
    }
  }

  /**
   * Create new AI configuration
   * POST /api/tenant/ai-config/settings
   */
  async createSetting(req, res) {
    let connection;
    try {
      const tenantId = req.user.tenantId;
      const {
        evolution_instance_id,
        provider,
        model_name,
        api_key,
        persona_name,
        persona_description,
        system_prompt,
        temperature = 0.7,
        max_tokens = 1000,
        business_hours_start = '08:00',
        business_hours_end = '18:00',
        business_days = 'monday,tuesday,wednesday,thursday,friday,saturday',
        auto_response_enabled = true,
        response_delay = 2
      } = req.body;

      // Validation
      if (!evolution_instance_id) {
        return res.status(400).json({
          error: 'Evolution instance is required'
        });
      }

      if (!provider || !model_name || !api_key || !persona_name) {
        return res.status(400).json({
          error: 'Provider, model, API key and persona name are required'
        });
      }

      if (!['deepseek', 'gpt', 'openai'].includes(provider)) {
        return res.status(400).json({
          error: 'Provider must be "deepseek", "gpt", or "openai"'
        });
      }

      if (!this.isValidTime(business_hours_start) || !this.isValidTime(business_hours_end)) {
        return res.status(400).json({
          error: 'Times must be in HH:MM format'
        });
      }

      connection = await pool.getConnection();

      // Verify instance exists and belongs to tenant
      const [instances] = await connection.execute(
        'SELECT id, status FROM evolution_instances WHERE id = ? AND tenant_id = ?',
        [evolution_instance_id, tenantId]
      );

      if (instances.length === 0) {
        return res.status(404).json({
          error: 'Evolution instance not found'
        });
      }

      // Check if configuration already exists for this instance
      const [existing] = await connection.execute(
        'SELECT id FROM ai_configurations WHERE tenant_id = ? AND evolution_instance_id = ?',
        [tenantId, evolution_instance_id]
      );

      if (existing.length > 0) {
        return res.status(400).json({
          error: 'AI configuration already exists for this instance'
        });
      }

      // Encrypt API key
      const encryptedApiKey = this.encryptData(api_key);

      // Normalize times to HH:MM format
      const normalizedStartTime = this.normalizeTime(business_hours_start);
      const normalizedEndTime = this.normalizeTime(business_hours_end);

      // Deactivate other configurations for this instance if this one is active
      if (req.body.active) {
        await connection.execute(
          'UPDATE ai_configurations SET active = FALSE WHERE tenant_id = ? AND evolution_instance_id = ?',
          [tenantId, evolution_instance_id]
        );
      }

      const [result] = await connection.execute(
        `INSERT INTO ai_configurations (
          tenant_id, evolution_instance_id, provider, model_name, api_key, persona_name, persona_description,
          system_prompt, temperature, max_tokens, active,
          business_hours_start, business_hours_end, business_days,
          auto_response_enabled, response_delay
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
        [
          tenantId, evolution_instance_id, provider, model_name, encryptedApiKey, persona_name, persona_description,
          system_prompt, temperature, max_tokens, req.body.active || false,
          normalizedStartTime, normalizedEndTime, business_days,
          auto_response_enabled, response_delay
        ]
      );

      res.json({
        success: true,
        message: 'AI configuration created successfully',
        id: result.insertId
      });
    } catch (error) {
      logger.error('Error creating AI configuration:', error);
      res.status(500).json({ error: 'Error creating AI configuration' });
    } finally {
      if (connection) connection.release();
    }
  }

  /**
   * Update AI configuration
   * PUT /api/tenant/ai-config/settings/:id
   */
  async updateSetting(req, res) {
    let connection;
    try {
      const tenantId = req.user.tenantId;
      const { id } = req.params;
      const {
        provider,
        model_name,
        api_key,
        persona_name,
        persona_description,
        system_prompt,
        temperature,
        max_tokens,
        business_hours_start,
        business_hours_end,
        business_days,
        auto_response_enabled,
        response_delay
      } = req.body;

      connection = await pool.getConnection();

      // Verify ownership
      const [existing] = await connection.execute(
        'SELECT id, evolution_instance_id FROM ai_configurations WHERE id = ? AND tenant_id = ?',
        [id, tenantId]
      );

      if (existing.length === 0) {
        return res.status(404).json({ error: 'Configuration not found' });
      }

      // Build update query
      let updateFields = [];
      let updateValues = [];

      if (provider) {
        if (!['deepseek', 'gpt', 'openai'].includes(provider)) {
          return res.status(400).json({
            error: 'Provider must be "deepseek", "gpt", or "openai"'
          });
        }
        updateFields.push('provider = ?');
        updateValues.push(provider);
      }

      if (model_name) {
        updateFields.push('model_name = ?');
        updateValues.push(model_name);
      }

      if (api_key) {
        updateFields.push('api_key = ?');
        updateValues.push(this.encryptData(api_key));
      }

      if (persona_name) {
        updateFields.push('persona_name = ?');
        updateValues.push(persona_name);
      }

      if (persona_description !== undefined) {
        updateFields.push('persona_description = ?');
        updateValues.push(persona_description);
      }

      if (system_prompt !== undefined) {
        updateFields.push('system_prompt = ?');
        updateValues.push(system_prompt);
      }

      if (temperature !== undefined) {
        updateFields.push('temperature = ?');
        updateValues.push(temperature);
      }

      if (max_tokens !== undefined) {
        updateFields.push('max_tokens = ?');
        updateValues.push(max_tokens);
      }

      if (business_hours_start) {
        if (!this.isValidTime(business_hours_start)) {
          return res.status(400).json({
            error: 'Business hours start must be in HH:MM format'
          });
        }
        updateFields.push('business_hours_start = ?');
        updateValues.push(this.normalizeTime(business_hours_start));
      }

      if (business_hours_end) {
        if (!this.isValidTime(business_hours_end)) {
          return res.status(400).json({
            error: 'Business hours end must be in HH:MM format'
          });
        }
        updateFields.push('business_hours_end = ?');
        updateValues.push(this.normalizeTime(business_hours_end));
      }

      if (business_days) {
        updateFields.push('business_days = ?');
        updateValues.push(business_days);
      }

      if (auto_response_enabled !== undefined) {
        updateFields.push('auto_response_enabled = ?');
        updateValues.push(auto_response_enabled);
      }

      if (response_delay !== undefined) {
        updateFields.push('response_delay = ?');
        updateValues.push(response_delay);
      }

      if (updateFields.length === 0) {
        return res.status(400).json({ error: 'No fields to update' });
      }

      updateFields.push('updated_at = CURRENT_TIMESTAMP');
      updateValues.push(id, tenantId);

      await connection.execute(
        `UPDATE ai_configurations SET ${updateFields.join(', ')} WHERE id = ? AND tenant_id = ?`,
        updateValues
      );

      res.json({
        success: true,
        message: 'Configuration updated successfully'
      });
    } catch (error) {
      logger.error('Error updating configuration:', error);
      res.status(500).json({ error: 'Error updating configuration' });
    } finally {
      if (connection) connection.release();
    }
  }

  /**
   * Toggle AI configuration active status
   * PATCH /api/tenant/ai-config/settings/:id/toggle
   */
  async toggleSetting(req, res) {
    let connection;
    try {
      const tenantId = req.user.tenantId;
      const { id } = req.params;
      const { active } = req.body;

      if (typeof active !== 'boolean') {
        return res.status(400).json({ error: 'Active status must be boolean' });
      }

      connection = await pool.getConnection();

      // Verify ownership and get instance
      const [existing] = await connection.execute(
        'SELECT id, evolution_instance_id FROM ai_configurations WHERE id = ? AND tenant_id = ?',
        [id, tenantId]
      );

      if (existing.length === 0) {
        return res.status(404).json({ error: 'Configuration not found' });
      }

      if (active) {
        // Deactivate all other configurations for this instance
        await connection.execute(
          'UPDATE ai_configurations SET active = FALSE WHERE tenant_id = ? AND evolution_instance_id = ?',
          [tenantId, existing[0].evolution_instance_id]
        );
      }

      // Activate/deactivate the specific configuration
      await connection.execute(
        'UPDATE ai_configurations SET active = ? WHERE id = ? AND tenant_id = ?',
        [active, id, tenantId]
      );

      res.json({
        success: true,
        message: `Configuration ${active ? 'activated' : 'deactivated'} successfully`
      });
    } catch (error) {
      logger.error('Error toggling configuration:', error);
      res.status(500).json({ error: 'Error toggling configuration' });
    } finally {
      if (connection) connection.release();
    }
  }

  /**
   * Delete AI configuration
   * DELETE /api/tenant/ai-config/settings/:id
   */
  async deleteSetting(req, res) {
    let connection;
    try {
      const tenantId = req.user.tenantId;
      const { id } = req.params;

      connection = await pool.getConnection();

      const [result] = await connection.execute(
        'DELETE FROM ai_configurations WHERE id = ? AND tenant_id = ?',
        [id, tenantId]
      );

      if (result.affectedRows === 0) {
        return res.status(404).json({ error: 'Configuration not found' });
      }

      res.json({
        success: true,
        message: 'Configuration deleted successfully'
      });
    } catch (error) {
      logger.error('Error deleting configuration:', error);
      res.status(500).json({ error: 'Error deleting configuration' });
    } finally {
      if (connection) connection.release();
    }
  }

  /**
   * Test AI configuration
   * POST /api/tenant/ai-config/test/:id
   */
  async testConfiguration(req, res) {
    let connection;
    try {
      const tenantId = req.user.tenantId;
      const { id } = req.params;
      const { test_message = 'Hello, this is a connection test.' } = req.body;

      connection = await pool.getConnection();

      const [configs] = await connection.execute(
        'SELECT * FROM ai_configurations WHERE id = ? AND tenant_id = ?',
        [id, tenantId]
      );

      if (configs.length === 0) {
        return res.status(404).json({ error: 'Configuration not found' });
      }

      const config = configs[0];
      const apiKey = this.decryptData(config.api_key);

      let testResult;

      if (config.provider === 'deepseek') {
        testResult = await this.testDeepSeekConnection(apiKey, config, test_message);
      } else if (config.provider === 'gpt' || config.provider === 'openai') {
        testResult = await this.testGPTConnection(apiKey, config, test_message);
      } else {
        return res.status(400).json({ error: 'Provider not supported' });
      }

      res.json(testResult);
    } catch (error) {
      logger.error('Error testing configuration:', error);
      res.status(500).json({ error: 'Error testing configuration' });
    } finally {
      if (connection) connection.release();
    }
  }

  /**
   * Get available models by provider
   * GET /api/tenant/ai-config/models/:provider
   */
  async getModels(req, res) {
    try {
      const { provider } = req.params;

      let models = [];

      if (provider === 'deepseek') {
        models = [
          {
            id: 'deepseek-chat',
            name: 'DeepSeek Chat',
            description: 'Main model for general conversations',
            max_tokens: 4096
          },
          {
            id: 'deepseek-coder',
            name: 'DeepSeek Coder',
            description: 'Specialized in programming and code',
            max_tokens: 4096
          }
        ];
      } else if (provider === 'gpt' || provider === 'openai') {
        models = [
          {
            id: 'gpt-3.5-turbo',
            name: 'GPT-3.5 Turbo',
            description: 'Fast and efficient for general conversations',
            max_tokens: 4096
          },
          {
            id: 'gpt-4',
            name: 'GPT-4',
            description: 'Most advanced model with better understanding',
            max_tokens: 8192
          },
          {
            id: 'gpt-4-turbo',
            name: 'GPT-4 Turbo',
            description: 'Optimized version of GPT-4',
            max_tokens: 128000
          }
        ];
      } else {
        return res.status(400).json({ error: 'Provider not supported' });
      }

      res.json(models);
    } catch (error) {
      logger.error('Error fetching models:', error);
      res.status(500).json({ error: 'Error fetching models' });
    }
  }

  /**
   * Get AI usage statistics
   * GET /api/tenant/ai-config/stats
   */
  async getStats(req, res) {
    let connection;
    try {
      const tenantId = req.user.tenantId;

      connection = await pool.getConnection();

      // Total messages from bot today
      const [todayBot] = await connection.execute(
        `SELECT COUNT(*) as count 
         FROM messages 
         WHERE tenant_id = ? AND DATE(timestamp) = CURDATE() 
         AND is_from_bot = TRUE`,
        [tenantId]
      );

      // Total messages from bot this week
      const [weekBot] = await connection.execute(
        `SELECT COUNT(*) as count 
         FROM messages 
         WHERE tenant_id = ? AND timestamp >= DATE_SUB(NOW(), INTERVAL 7 DAY)
         AND is_from_bot = TRUE`,
        [tenantId]
      );

      // Total conversations with bot messages
      const [conversations] = await connection.execute(
        `SELECT COUNT(DISTINCT conversation_id) as count
         FROM messages 
         WHERE tenant_id = ? AND is_from_bot = TRUE
         AND timestamp >= DATE_SUB(NOW(), INTERVAL 7 DAY)`,
        [tenantId]
      );

      // Active configuration
      const [activeConfig] = await connection.execute(
        `SELECT provider, model_name, persona_name
         FROM ai_configurations 
         WHERE tenant_id = ? AND active = TRUE
         LIMIT 1`,
        [tenantId]
      );

      res.json({
        today_ai_messages: todayBot[0].count,
        week_ai_messages: weekBot[0].count,
        avg_response_time: 1.2, // Mock value - will be implemented when tracking is added
        active_config: activeConfig.length > 0 ? activeConfig[0] : null
      });
    } catch (error) {
      logger.error('Error fetching statistics:', error);
      res.status(500).json({ error: 'Error fetching statistics' });
    } finally {
      if (connection) connection.release();
    }
  }

  /**
   * Get available instances for AI configuration
   * GET /api/tenant/ai-config/instances
   */
  async getInstances(req, res) {
    let connection;
    try {
      const tenantId = req.user.tenantId;

      connection = await pool.getConnection();

      const [instances] = await connection.execute(
        `SELECT 
          ei.id,
          ei.instance_name,
          ei.phone_number,
          ei.status,
          ac.id as config_id,
          ac.provider,
          ac.active as config_active
        FROM evolution_instances ei
        LEFT JOIN ai_configurations ac ON ei.id = ac.evolution_instance_id AND ac.tenant_id = ?
        WHERE ei.tenant_id = ? AND ei.is_active = TRUE
        ORDER BY ei.instance_name ASC`,
        [tenantId, tenantId]
      );

      res.json({
        success: true,
        data: instances
      });
    } catch (error) {
      logger.error('Error fetching instances:', error);
      res.status(500).json({ error: 'Error fetching instances' });
    } finally {
      if (connection) connection.release();
    }
  }

  // Helper methods
  encryptData(text) {
    const keyString = process.env.ENCRYPTION_KEY || 'default-key-change-in-production-32';
    const key = crypto.createHash('sha256').update(keyString).digest();
    const iv = crypto.randomBytes(16);

    const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
    let encrypted = cipher.update(text, 'utf8', 'hex');
    encrypted += cipher.final('hex');

    return iv.toString('hex') + ':' + encrypted;
  }

  decryptData(encryptedText) {
    const keyString = process.env.ENCRYPTION_KEY || 'default-key-change-in-production-32';
    const key = crypto.createHash('sha256').update(keyString).digest();

    const textParts = encryptedText.split(':');
    const iv = Buffer.from(textParts.shift(), 'hex');
    const encrypted = textParts.join(':');

    const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
    let decrypted = decipher.update(encrypted, 'hex', 'utf8');
    decrypted += decipher.final('utf8');

    return decrypted;
  }

  isValidTime(timeString) {
    // Accept both HH:MM and HH:MM:SS formats
    if (!timeString) return false;
    
    // Remove seconds if present (HH:MM:SS -> HH:MM)
    const timeParts = timeString.split(':');
    if (timeParts.length === 3) {
      timeString = `${timeParts[0]}:${timeParts[1]}`;
    }
    
    return /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/.test(timeString);
  }

  normalizeTime(timeString) {
    // Normalize time to HH:MM format (remove seconds if present)
    if (!timeString) return timeString;
    
    const timeParts = timeString.split(':');
    if (timeParts.length >= 2) {
      return `${timeParts[0]}:${timeParts[1]}`;
    }
    
    return timeString;
  }

  async testDeepSeekConnection(apiKey, config, testMessage) {
    try {
      const response = await axios.post(
        'https://api.deepseek.com/v1/chat/completions',
        {
          model: config.model_name,
          messages: [
            {
              role: 'system',
              content: config.system_prompt || 'You are a helpful assistant.'
            },
            {
              role: 'user',
              content: testMessage
            }
          ],
          temperature: parseFloat(config.temperature) || 0.7,
          max_tokens: Math.min(parseInt(config.max_tokens) || 1000, 100)
        },
        {
          headers: {
            Authorization: `Bearer ${apiKey}`,
            'Content-Type': 'application/json'
          },
          timeout: 10000
        }
      );

      return {
        success: true,
        message: 'Connection with DeepSeek established successfully',
        response: response.data.choices[0].message.content,
        usage: response.data.usage
      };
    } catch (error) {
      return {
        success: false,
        error: error.response?.data?.error?.message || error.message || 'Error connecting with DeepSeek'
      };
    }
  }

  async testGPTConnection(apiKey, config, testMessage) {
    try {
      const response = await axios.post(
        'https://api.openai.com/v1/chat/completions',
        {
          model: config.model_name,
          messages: [
            {
              role: 'system',
              content: config.system_prompt || 'You are a helpful assistant.'
            },
            {
              role: 'user',
              content: testMessage
            }
          ],
          temperature: parseFloat(config.temperature) || 0.7,
          max_tokens: Math.min(parseInt(config.max_tokens) || 1000, 100)
        },
        {
          headers: {
            Authorization: `Bearer ${apiKey}`,
            'Content-Type': 'application/json'
          },
          timeout: 10000
        }
      );

      return {
        success: true,
        message: 'Connection with OpenAI GPT established successfully',
        response: response.data.choices[0].message.content,
        usage: response.data.usage
      };
    } catch (error) {
      return {
        success: false,
        error: error.response?.data?.error?.message || error.message || 'Error connecting with OpenAI'
      };
    }
  }
}

const aiConfigController = new AIConfigController();

module.exports = {
  getSettings: (req, res) => aiConfigController.getSettings(req, res),
  createSetting: (req, res) => aiConfigController.createSetting(req, res),
  updateSetting: (req, res) => aiConfigController.updateSetting(req, res),
  toggleSetting: (req, res) => aiConfigController.toggleSetting(req, res),
  deleteSetting: (req, res) => aiConfigController.deleteSetting(req, res),
  testConfiguration: (req, res) => aiConfigController.testConfiguration(req, res),
  getModels: (req, res) => aiConfigController.getModels(req, res),
  getStats: (req, res) => aiConfigController.getStats(req, res),
  getInstances: (req, res) => aiConfigController.getInstances(req, res)
};
