const styles = require('../config/styles.json');
const weights = require('../config/weights.json');

class Randomizer {
  constructor() {
    this.history = [];
    this.maxHistory = weights.antiRepetition.historySize;
  }

  // Weighted random selection
  weightedRandom(items, weightObj) {
    const totalWeight = Object.values(weightObj).reduce((sum, w) => sum + w, 0);
    let random = Math.random() * totalWeight;

    for (const [key, weight] of Object.entries(weightObj)) {
      random -= weight;
      if (random <= 0) {
        return key;
      }
    }

    return Object.keys(weightObj)[0];
  }

  // Select random item from array
  randomFromArray(array) {
    return array[Math.floor(Math.random() * array.length)];
  }

  // Calculate similarity between two styles
  calculateSimilarity(style1, style2) {
    if (!style1 || !style2) return 0;

    let similarity = 0;
    const similarityWeights = weights.antiRepetition.weights;

    // Background similarity
    if (style1.background?.id === style2.background?.id) {
      similarity += similarityWeights.background;
    }

    // Color scheme similarity
    if (style1.colorScheme?.id === style2.colorScheme?.id) {
      similarity += similarityWeights.colorScheme;
    }

    // Layout similarity
    if (style1.layout?.id === style2.layout?.id) {
      similarity += similarityWeights.layout;
    }

    // VS element similarity
    if (style1.vsElement?.id === style2.vsElement?.id) {
      similarity += similarityWeights.vsElement;
    }

    return similarity;
  }

  // Check if style is too similar to recent history
  isTooSimilar(newStyle) {
    const threshold = weights.antiRepetition.minDifferenceThreshold;

    for (const historicalStyle of this.history) {
      const similarity = this.calculateSimilarity(newStyle, historicalStyle);
      if (similarity > (1 - threshold)) {
        return true;
      }
    }

    return false;
  }

  // Add style to history
  addToHistory(style) {
    this.history.push(style);

    // Keep history size limited
    if (this.history.length > this.maxHistory) {
      this.history.shift();
    }
  }

  // Select background
  selectBackground(seriesType = 'comparison') {
    const seriesWeights = weights[seriesType];
    const bgType = this.weightedRandom(
      ['photorealistic', 'abstract'],
      seriesWeights.backgroundPreferences
    );

    const backgrounds = styles.backgrounds[bgType];
    return this.randomFromArray(backgrounds);
  }

  // Select color scheme
  selectColorScheme() {
    return this.randomFromArray(styles.colorSchemes);
  }

  // Select layout
  selectLayout(seriesType = 'comparison') {
    const seriesWeights = weights[seriesType];
    const layoutCategory = this.weightedRandom(
      Object.keys(seriesWeights.layoutPreferences),
      seriesWeights.layoutPreferences
    );

    const layouts = styles.layouts[layoutCategory];
    return this.randomFromArray(layouts);
  }

  // Select VS element
  selectVSElement(seriesType = 'comparison') {
    const seriesWeights = weights[seriesType];

    if (seriesWeights.vsElementPreferences) {
      const vsElementId = this.weightedRandom(
        Object.keys(seriesWeights.vsElementPreferences),
        seriesWeights.vsElementPreferences
      );

      return styles.vsElements.find(el => el.id === vsElementId);
    }

    return this.randomFromArray(styles.vsElements);
  }

  // Generate complete style with anti-repetition
  generateStyle(seriesType = 'comparison', maxAttempts = 10) {
    let attempts = 0;
    let selectedStyle = null;

    do {
      selectedStyle = {
        background: this.selectBackground(seriesType),
        colorScheme: this.selectColorScheme(),
        layout: this.selectLayout(seriesType),
        vsElement: this.selectVSElement(seriesType),
        seriesType
      };

      attempts++;

      if (attempts >= maxAttempts) {
        console.log('Max attempts reached, using current style');
        break;
      }

    } while (this.isTooSimilar(selectedStyle));

    // Add to history
    this.addToHistory(selectedStyle);

    return selectedStyle;
  }

  // Generate style with specific overrides
  generateStyleWithOverrides(seriesType = 'comparison', overrides = {}) {
    const baseStyle = this.generateStyle(seriesType);

    return {
      ...baseStyle,
      ...overrides
    };
  }

  // Clear history
  clearHistory() {
    this.history = [];
  }

  // Get history
  getHistory() {
    return this.history;
  }
}

module.exports = Randomizer;
