const express = require('express');
const router = express.Router();
const Feature = require('../models/feature');
const CustomFeature = require('../models/custom_feature');
const FeatureRule = require('../models/feature_rule');
const AdminNotification = require('../models/admin_notification');
const FeatureSimilarityService = require('../services/feature_similarity');
const database = require('../config/database');
const { v4: uuidv4 } = require('uuid');
const FeatureBusinessRules = require('../models/feature_business_rules');

// Initialize similarity service
const similarityService = new FeatureSimilarityService();

// GET /api/features/popular - Get popular features across all templates
router.get('/popular', async (req, res) => {
  try {
    const limit = parseInt(req.query.limit) || 10;
    console.log(`🔥 Fetching top ${limit} popular features...`);
    
    const features = await Feature.getPopularFeatures(limit);
    
    res.json({
      success: true,
      data: features,
      count: features.length,
      message: `Found ${features.length} popular features`
    });
  } catch (error) {
    console.error('❌ Error fetching popular features:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to fetch popular features',
      message: error.message
    });
  }
});

// GET /api/features/stats - Get feature statistics
router.get('/stats', async (req, res) => {
  try {
    console.log('📊 Fetching feature statistics...');
    const stats = await Feature.getStats();
    
    res.json({
      success: true,
      data: stats,
      message: 'Feature statistics retrieved successfully'
    });
  } catch (error) {
    console.error('❌ Error fetching feature stats:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to fetch feature statistics',
      message: error.message
    });
  }
});

// GET /api/features/search - Search features
router.get('/search', async (req, res) => {
  try {
    const { q: searchTerm, template_id } = req.query;
    
    if (!searchTerm) {
      return res.status(400).json({
        success: false,
        error: 'Search term required',
        message: 'Please provide a search term using the "q" parameter'
      });
    }
    
    console.log(`🔍 Searching features for: "${searchTerm}"`);
    
    const features = await Feature.search(searchTerm, template_id);
    
    res.json({
      success: true,
      data: features,
      count: features.length,
      message: `Found ${features.length} features matching "${searchTerm}"`
    });
  } catch (error) {
    console.error('❌ Error searching features:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to search features',
      message: error.message
    });
  }
});

// GET /api/features/similar - Find similar features
router.get('/similar', async (req, res) => {
  try {
    const { q: query, threshold = 0.7, limit = 5 } = req.query;
    
    if (!query) {
      return res.status(400).json({
        success: false,
        error: 'Query parameter required',
        message: 'Please provide a query parameter "q"'
      });
    }
    
    console.log(`🔍 Finding similar features for "${query}"`);
    
    const similarFeatures = await similarityService.findSimilarFeatures(
      query, 
      parseFloat(threshold), 
      parseInt(limit)
    );
    
    res.json({
      success: true,
      data: similarFeatures,
      count: similarFeatures.length,
      message: `Found ${similarFeatures.length} similar features`
    });
  } catch (error) {
    console.error('❌ Error finding similar features:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to find similar features',
      message: error.message
    });
  }
});

// GET /api/features/type/:type - Get features by type
router.get('/type/:type', async (req, res) => {
  try {
    const { type } = req.params;
    const limit = parseInt(req.query.limit) || 20;
    
    console.log(`🎯 Fetching ${type} features (limit: ${limit})`);
    
    const validTypes = ['essential', 'suggested', 'custom'];
    if (!validTypes.includes(type)) {
      return res.status(400).json({
        success: false,
        error: 'Invalid feature type',
        message: `Feature type must be one of: ${validTypes.join(', ')}`
      });
    }
    
    const features = await Feature.getByType(type, limit);
    
    res.json({
      success: true,
      data: features,
      count: features.length,
      message: `Found ${features.length} ${type} features`
    });
  } catch (error) {
    console.error('❌ Error fetching features by type:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to fetch features by type',
      message: error.message
    });
  }
});

// GET /api/features/:id - Get specific default feature (with aggregated business rules if present)
router.get('/:id', async (req, res) => {
  try {
    const { id } = req.params;
    console.log(`🔍 Fetching feature: ${id}`);
    
    const feature = await Feature.getById(id);
    
    if (!feature) {
      return res.status(404).json({
        success: false,
        error: 'Feature not found',
        message: `Feature with ID ${id} does not exist`
      });
    }
    
    // Try to fetch aggregated business rules for this feature from feature_business_rules using both keys
    try {
      const rulesQuery = `
        SELECT business_rules
        FROM feature_business_rules
        WHERE template_id = $1 AND (feature_id = $2 OR feature_id = $3)
        LIMIT 1
      `
      const rulesResult = await database.query(rulesQuery, [feature.template_id, String(id), feature.feature_id])
      const additional = rulesResult.rows?.[0]?.business_rules || null
      const payload = { ...feature, additional_business_rules: additional }
      return res.json({ success: true, data: payload, message: `Feature '${feature.name}' retrieved successfully` })
    } catch (rulesErr) {
      console.warn('⚠️ Failed to fetch aggregated rules for feature:', rulesErr.message)
      return res.json({ success: true, data: feature, message: `Feature '${feature.name}' retrieved successfully` })
    }
  } catch (error) {
    console.error('❌ Error fetching feature:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to fetch feature',
      message: error.message
    });
  }
});

// POST /api/features - Create new feature directly in template_features table
router.post('/', async (req, res) => {
  try {
    const featureData = req.body;
    console.log('🏗️ Creating new feature:', featureData.name);
    console.log('🔍 API Route - Received feature data:', {
      name: featureData.name,
      logic_rules: featureData.logic_rules,
      business_rules: featureData.business_rules,
      template_id: featureData.template_id
    });
    const requiredFields = ['template_id', 'name', 'complexity'];
    for (const field of requiredFields) {
      if (!featureData[field]) {
        return res.status(400).json({ success: false, error: 'Validation error', message: `Field '${field}' is required` });
      }
    }
    const validComplexity = ['low', 'medium', 'high'];
    if (!validComplexity.includes(featureData.complexity)) {
      return res.status(400).json({ success: false, error: 'Invalid complexity', message: `Complexity must be one of: ${validComplexity.join(', ')}` });
    }

    // Validate that template_id exists in either templates or custom_templates table
    const templateCheck = await database.query(`
      SELECT id, title, 'default' as template_type FROM templates WHERE id = $1 AND is_active = true
      UNION
      SELECT id, title, 'custom' as template_type FROM custom_templates WHERE id = $1
    `, [featureData.template_id]);

    if (templateCheck.rows.length === 0) {
      console.error('❌ Template not found in either table:', featureData.template_id);
      return res.status(400).json({ 
        success: false, 
        error: 'Template not found', 
        message: `Template with ID ${featureData.template_id} does not exist in templates or custom_templates` 
      });
    }

    const templateType = templateCheck.rows[0].template_type;

    // Allow admin-approved features to be created in template_features table regardless of template type
    // Only redirect regular user-created features for custom templates
    const isAdminApproval = featureData.feature_type === 'essential' && featureData.created_by_user !== true;
    
    if (templateType === 'custom' && !isAdminApproval) {
      console.log('🔄 Redirecting to custom features endpoint for custom template');
      return res.status(400).json({
        success: false,
        error: 'Invalid template type',
        message: 'Features for custom templates should be created using the /api/features/custom endpoint'
      });
    }

    const feature = await Feature.create({
      template_id: featureData.template_id,
      feature_id: featureData.id,
      name: featureData.name,
      description: featureData.description,
      feature_type: featureData.feature_type || 'essential',
      complexity: featureData.complexity,
      display_order: featureData.display_order || 999,
      is_default: featureData.is_default || false,
      created_by_user: featureData.created_by_user || false,
      logic_rules: featureData.logic_rules,
      business_rules: featureData.business_rules,
    });

    // Also persist into feature_business_rules for defaults/suggested features
    try {
      // Prefer structured business_rules when provided; fallback to flat logic_rules
      const rules = (featureData.business_rules ?? featureData.logic_rules ?? []);
      if (featureData.template_id && (featureData.id || feature?.feature_id)) {
        await FeatureBusinessRules.upsert(
          featureData.template_id,
          featureData.id || feature.feature_id,
          rules
        );
      }
    } catch (ruleErr) {
      console.error('⚠️ Failed to persist feature business rules (default/suggested):', ruleErr.message);
    }

    res.status(201).json({ success: true, data: feature, message: `Feature '${feature.name}' created successfully in template_features table` });
  } catch (error) {
    console.error('❌ Error creating feature:', error.message);
    if (error.code === '23505') {
      return res.status(409).json({ success: false, error: 'Feature already exists', message: 'A feature with this ID already exists for this template' });
    }
    res.status(500).json({ success: false, error: 'Failed to create feature', message: error.message });
  }
});

// PUT /api/features/:id/usage - Increment feature usage
router.put('/:id/usage', async (req, res) => {
  try {
    const { id } = req.params;
    const { user_session, project_id } = req.body;
    
    console.log(`📈 Incrementing usage for feature: ${id}`);
    
    const feature = await Feature.getById(id);
    if (!feature) {
      return res.status(404).json({
        success: false,
        error: 'Feature not found',
        message: `Feature with ID ${id} does not exist`
      });
    }
    
    await feature.incrementUsage(user_session, project_id);
    
    res.json({
      success: true,
      data: feature,
      message: `Usage count updated for '${feature.name}' (now: ${feature.usage_count})`
    });
  } catch (error) {
    console.error('❌ Error updating feature usage:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to update feature usage',
      message: error.message
    });
  }
});

// PUT /api/features/:id/rating - Update feature rating
router.put('/:id/rating', async (req, res) => {
  try {
    const { id } = req.params;
    const { rating } = req.body;
    
    console.log(`⭐ Updating rating for feature: ${id} to ${rating}`);
    
    // Validate rating
    if (typeof rating !== 'number' || rating < 0 || rating > 5) {
      return res.status(400).json({
        success: false,
        error: 'Invalid rating',
        message: 'Rating must be a number between 0 and 5'
      });
    }
    
    const feature = await Feature.getById(id);
    if (!feature) {
      return res.status(404).json({
        success: false,
        error: 'Feature not found',
        message: `Feature with ID ${id} does not exist`
      });
    }
    
    await feature.updateRating(rating);
    
    res.json({
      success: true,
      data: feature,
      message: `Rating updated for '${feature.name}' to ${rating}/5`
    });
  } catch (error) {
    console.error('❌ Error updating feature rating:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to update feature rating',
      message: error.message
    });
  }
});

// PUT /api/features/:id - Update feature (handles both regular and custom features)
router.put('/:id', async (req, res) => {
  try {
    const { id } = req.params;
    const updateData = req.body;

    // First try to find as a regular feature
    let existing = await Feature.getById(id);
    let isCustomFeature = false;

    // If not found as regular feature, try as custom feature
    if (!existing) {
      existing = await CustomFeature.getById(id);
      isCustomFeature = true;
    }

    if (!existing) {
      return res.status(404).json({
        success: false,
        error: 'Feature not found',
        message: `Feature with ID ${id} does not exist`
      });
    }

    // Validate enums if provided
    const validTypes = ['essential', 'suggested', 'custom'];
    const validComplexity = ['low', 'medium', 'high'];
    if (updateData.feature_type && !validTypes.includes(updateData.feature_type)) {
      return res.status(400).json({ success: false, error: 'Invalid feature type' });
    }
    if (updateData.complexity && !validComplexity.includes(updateData.complexity)) {
      return res.status(400).json({ success: false, error: 'Invalid complexity' });
    }

    let updated;
    if (isCustomFeature) {
      // Update custom feature (only in custom_features table)
      updated = await CustomFeature.update(id, updateData);
    } else {
      // Update regular feature (only in template_features table)
      updated = await Feature.update(id, updateData);
    }

    res.json({
      success: true,
      data: updated,
      message: `Feature '${updated.name}' updated successfully`
    });
  } catch (error) {
    console.error('❌ Error updating feature:', error.message);
    res.status(500).json({ success: false, error: 'Failed to update feature', message: error.message });
  }
});

// DELETE /api/features/:id - Delete default/suggested feature (template_features)
router.delete('/:id', async (req, res) => {
  try {
    const { id } = req.params;
    const existing = await Feature.getById(id);
    if (!existing) {
      return res.status(404).json({
        success: false,
        error: 'Feature not found',
        message: `Feature with ID ${id} does not exist`
      });
    }

    await Feature.delete(id);
    res.json({ success: true, message: `Feature '${existing.name}' deleted successfully` });
  } catch (error) {
    console.error('❌ Error deleting feature:', error.message);
    res.status(500).json({ success: false, error: 'Failed to delete feature', message: error.message });
  }
});

// ---------- CUSTOM FEATURES ROUTES ----------

// POST /api/features/custom - create a custom feature (custom_features table)
router.post('/custom', async (req, res) => {
  try {
    const data = req.body || {}
    // Normalize and validate JSON-like fields to avoid invalid input syntax for type json
    const tryParseJson = (value) => {
      if (value === undefined || value === null || value === '') return null;
      if (typeof value === 'string') {
        const trimmed = value.trim();
        // Only attempt to parse if it looks like JSON; otherwise pass through as plain string
        if ((trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'))) {
          try { return JSON.parse(trimmed); } catch {
            // If it looks like JSON but fails to parse, fallback to null so we don't send invalid jsonb
            return null;
          }
        }
        // Allow plain strings; model will stringify safely for jsonb columns
        return trimmed;
      }
      return value;
    }

    // Be lenient: normalize but do not reject if strings are not valid JSON
    if (data.business_rules !== undefined) data.business_rules = tryParseJson(data.business_rules)
    if (data.logic_rules !== undefined) data.logic_rules = tryParseJson(data.logic_rules)
    if (data.technical_requirements !== undefined) data.technical_requirements = tryParseJson(data.technical_requirements)
    console.log('🔍 Custom feature creation request:', { template_id: data.template_id, name: data.name, complexity: data.complexity, description: data.description })
    const required = ['template_id', 'name', 'complexity']
    for (const f of required) {
      if (!data[f]) {
        return res.status(400).json({ success: false, error: 'Validation error', message: `Field '${f}' is required` })
      }
    }
    const validComplexity = ['low', 'medium', 'high']
    if (!validComplexity.includes(data.complexity)) {
      return res.status(400).json({ success: false, error: 'Invalid complexity' })
    }

    const templateCheck = await database.query(`
      SELECT id, title, 'default' as template_type FROM templates WHERE id = $1 AND is_active = true
      UNION
      SELECT id, title, 'custom' as template_type FROM custom_templates WHERE id = $1
    `, [data.template_id])

    if (templateCheck.rows.length === 0) {
      console.error('❌ Template not found in either table:', data.template_id)
      return res.status(400).json({ success: false, error: 'Template not found', message: `Template with ID ${data.template_id} does not exist in templates or custom_templates` })
    }

    let similarityInfo = null;
    try {
      const duplicateCheck = await similarityService.checkForDuplicates(data.name, 0.8);
      if (duplicateCheck.isDuplicate) {
        similarityInfo = { isDuplicate: true, canonicalFeature: duplicateCheck.canonicalFeature, similarityScore: duplicateCheck.similarityScore, matchType: duplicateCheck.matchType };
      }
    } catch (similarityError) {
      console.error('Error checking for duplicates:', similarityError.message);
    }

    const created = await CustomFeature.create({
      template_id: data.template_id,
      template_type: templateCheck.rows[0]?.template_type === 'custom' ? 'custom' : 'default',
      name: data.name,
      description: data.description,
      complexity: data.complexity,
      // Persist incoming structured fields on the row as well
      business_rules: data.business_rules ?? (data.logic_rules ? [{ requirement: 'Aggregated', rules: data.logic_rules }] : null),
      technical_requirements: data.technical_requirements ?? null,
      approved: false,
      usage_count: 1,
      created_by_user_session: data.created_by_user_session,
      status: 'pending',
      similarity_score: similarityInfo?.similarityScore || null,
      canonical_feature_id: similarityInfo?.canonicalFeature?.id || null,
    })

    try { await AdminNotification.notifyNewFeature(created.id, created.name); } catch (e) { console.error('⚠️ Failed to create admin notification:', e.message); }

    // Custom features are only stored in custom_features table, not mirrored to template_features

    // Persist aggregated rules (using actual custom feature ID)
    try {
      // Prefer structured business_rules; fallback to flat logic_rules
      const rules = (data.business_rules ?? data.logic_rules ?? []);
      if (Array.isArray(rules) && rules.length > 0) {
        await FeatureBusinessRules.upsert(data.template_id, created.id, rules);
      } else {
        // If nothing to upsert, keep a copy on the custom_features row
        try { await CustomFeature.update(created.id, { business_rules: rules }); } catch {}
      }
    } catch (ruleErr) {
      // Fallback: persist on the custom_features row so edit can still load them
      console.error('⚠️ Failed to persist custom feature business rules (feature_business_rules). Falling back to custom_features.business_rules:', ruleErr.message);
      try {
        const fallbackRules = (data.business_rules ?? data.logic_rules ?? []);
        await CustomFeature.update(created.id, { business_rules: fallbackRules });
      } catch (fallbackErr) {
        console.error('⚠️ Fallback save to custom_features.business_rules also failed:', fallbackErr.message);
      }
    }

    const response = { success: true, data: created, message: `Custom feature '${created.name}' created successfully and submitted for admin review` };
    if (similarityInfo) { response.similarityInfo = similarityInfo; response.message += '. Similar features were found and will be reviewed by admin.'; }
    return res.status(201).json(response);
  } catch (e) {
    console.error('Error creating custom feature:', e.message)
    return res.status(500).json({ success: false, error: 'Failed to create custom feature', message: e.message })
  }
})

// GET /api/features/templates/:id/features - merged default + custom features
router.get('/templates/:templateId/features', async (req, res) => {
  try {
    const { templateId } = req.params;
    // Include aggregated rules for default/suggested features
    const defaultsQuery = `
      SELECT 
        tf.*, 
        fbr.business_rules AS additional_business_rules
      FROM template_features tf
      LEFT JOIN feature_business_rules fbr
        ON tf.template_id = fbr.template_id
        AND (
          fbr.feature_id = (tf.id::text)
          OR fbr.feature_id = tf.feature_id
        )
      WHERE tf.template_id = $1
      ORDER BY 
        CASE tf.feature_type 
          WHEN 'essential' THEN 1 
          WHEN 'suggested' THEN 2 
          WHEN 'custom' THEN 3 
        END,
        tf.display_order,
        tf.usage_count DESC,
        tf.name
    `;
    const defaultsResult = await database.query(defaultsQuery, [templateId]);
    const defaults = defaultsResult.rows;
    // Fetch custom features with joined business rules like in templates.js
    const customFeaturesQuery = `
      SELECT 
        cf.id,
        cf.template_id,
        cf.name,
        cf.description,
        cf.complexity,
        cf.business_rules,
        cf.technical_requirements,
        'custom' as feature_type,
        cf.created_at,
        cf.updated_at,
        cf.status,
        cf.approved,
        cf.usage_count,
        0 as user_rating,
        false as is_default,
        true as created_by_user,
        fbr.business_rules as additional_business_rules
      FROM custom_features cf
      LEFT JOIN feature_business_rules fbr 
        ON cf.template_id = fbr.template_id 
        AND (
          fbr.feature_id = (cf.id::text)
          OR fbr.feature_id = ('custom_' || cf.id::text)
        )
      WHERE cf.template_id = $1
      ORDER BY cf.created_at DESC
    `;
    const customsResult = await database.query(customFeaturesQuery, [templateId]);
    const customs = customsResult.rows;
    // Map custom model to template-like shape
    const customAsTemplate = customs.map(cf => ({
      id: cf.id,
      template_id: cf.template_id,
      feature_id: `custom_${cf.id}`,
      name: cf.name,
      description: cf.description,
      feature_type: 'custom',
      complexity: cf.complexity,
      display_order: 999,
      usage_count: cf.usage_count || 0,
      user_rating: 0,
      is_default: false,
      created_by_user: true,
      created_at: cf.created_at,
      updated_at: cf.updated_at,
    }));
    res.json({ success: true, data: [...defaults, ...customAsTemplate] });
  } catch (e) {
    res.status(500).json({ success: false, error: 'Failed to fetch merged features', message: e.message });
  }
});

// PUT /api/features/custom/:id - update custom feature
router.put('/custom/:id', async (req, res) => {
  try {
    const { id } = req.params;
    const existing = await CustomFeature.getById(id);
    if (!existing) return res.status(404).json({ success: false, error: 'Not found' });
    const updates = req.body || {}
    const updated = await CustomFeature.update(id, updates);
    
    // Custom features are only stored in custom_features table, no mirroring needed
    res.json({ success: true, data: updated, message: `Custom feature '${updated.name}' updated successfully` });
  } catch (e) {
    res.status(500).json({ success: false, error: 'Failed to update custom feature', message: e.message });
  }
});

// DELETE /api/features/custom/:id - delete custom feature
router.delete('/custom/:id', async (req, res) => {
  try {
    const { id } = req.params;

    // Find and delete from custom_features table
    const existing = await CustomFeature.getById(id);
    if (!existing) {
      return res.status(404).json({ success: false, error: 'Not found', message: 'Custom feature not found' });
    }

    // Delete the custom feature
    await CustomFeature.delete(id);
    
    // Cleanup business rules if present
    try {
      await database.query('DELETE FROM feature_business_rules WHERE template_id = $1 AND feature_id = $2', [existing.template_id, id])
    } catch (cleanupErr) { 
      console.error('Failed to cleanup business rules:', cleanupErr.message) 
    }

    return res.json({ success: true, message: `Custom feature '${existing.name}' deleted successfully` });
  } catch (e) {
    res.status(500).json({ success: false, error: 'Failed to delete custom feature', message: e.message });
  }
});

module.exports = router;