const database = require('../config/database');
const { v4: uuidv4 } = require('uuid');

let cachedHasRuleJson = null;

async function hasRuleJsonColumn() {
  if (cachedHasRuleJson !== null) return cachedHasRuleJson;
  try {
    const q = `
      SELECT 1 FROM information_schema.columns
      WHERE table_schema = 'public' AND table_name = 'feature_rules' AND column_name = 'rule_json'
      LIMIT 1
    `;
    const result = await database.query(q);
    cachedHasRuleJson = result.rows.length > 0;
  } catch (e) {
    cachedHasRuleJson = false;
  }
  return cachedHasRuleJson;
}

class FeatureRule {
  constructor(data = {}) {
    this.id = data.id;
    this.template_id = data.template_id;
    this.template_feature_id = data.template_feature_id;
    this.feature_id = data.feature_id;
    this.rule_text = data.rule_text;
    this.rule_order = data.rule_order;
    this.created_at = data.created_at;
  }

  static async createMany(params) {
    const { template_id, template_feature_id, feature_id, rules } = params;
    if (!Array.isArray(rules) || rules.length === 0) return [];

    const includeJson = await hasRuleJsonColumn();
    try {
      console.log('[FeatureRule.createMany] start', {
        template_id,
        template_feature_id,
        feature_id,
        rules_count: rules.length,
        has_rule_json_column: includeJson
      });
    } catch {}

    const values = [];
    const placeholders = [];
    let idx = 1;
    for (let i = 0; i < rules.length; i++) {
      const id = uuidv4();
      if (includeJson) {
        placeholders.push(`($${idx++}, $${idx++}, $${idx++}, $${idx++}, $${idx++}, $${idx++}, $${idx++})`);
      } else {
        placeholders.push(`($${idx++}, $${idx++}, $${idx++}, $${idx++}, $${idx++}, $${idx++})`);
      }
      // rules[i] can be string or object; store string in rule_text, and JSON when available
      const rule = rules[i];
      let ruleText;
      let ruleJson = null;
      if (typeof rule === 'object' && rule !== null) {
        ruleText = JSON.stringify(rule);
        ruleJson = rule;
      } else if (typeof rule === 'string') {
        ruleText = rule;
        const trimmed = rule.trim();
        if ((trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'))) {
          try {
            ruleJson = JSON.parse(trimmed);
          } catch (e) {
            ruleJson = null; // keep as plain text if not valid JSON
          }
        }
      } else {
        ruleText = String(rule);
      }
      if (includeJson) {
        values.push(id, template_id, template_feature_id || null, feature_id, ruleText, i, ruleJson);
      } else {
        values.push(id, template_id, template_feature_id || null, feature_id, ruleText, i);
      }
    }

    const insertSql = includeJson
      ? `
        INSERT INTO feature_rules (id, template_id, template_feature_id, feature_id, rule_text, rule_order, rule_json)
        VALUES ${placeholders.join(', ')}
        RETURNING *
      `
      : `
        INSERT INTO feature_rules (id, template_id, template_feature_id, feature_id, rule_text, rule_order)
        VALUES ${placeholders.join(', ')}
        RETURNING *
      `;
    try {
      console.log('[FeatureRule.createMany] executing insert', {
        columns: includeJson
          ? ['id','template_id','template_feature_id','feature_id','rule_text','rule_order','rule_json']
          : ['id','template_id','template_feature_id','feature_id','rule_text','rule_order'],
        rows: rules.length
      });
      const result = await database.query(insertSql, values);
      console.log('[FeatureRule.createMany] success', { inserted: result.rows.length });
      return result.rows.map((r) => new FeatureRule(r));
    } catch (e) {
      console.error('[FeatureRule.createMany] DB error:', e.message);
      throw e;
    }
  }

  static async getByTemplateFeatureId(template_feature_id) {
    const result = await database.query(
      `SELECT * FROM feature_rules WHERE template_feature_id = $1 ORDER BY rule_order ASC`,
      [template_feature_id]
    );
    return result.rows.map((r) => new FeatureRule(r));
  }
}

module.exports = FeatureRule;


