lib/cw_card_utils/deck_comparator.rb



# frozen_string_literal: true

module CwCardUtils
  class DeckComparator
    attr_reader :deck_a, :deck_b, :analysis

    WEIGHTS = {
      archetype: 0.30,
      curve:     0.25,
      synergy:   0.25,
      interaction: 0.20,
    }.freeze

    def initialize(deck_a, deck_b)
      @deck_a = deck_a
      @deck_b = deck_b
      @analysis = {}
    end

    def compare
      results = {
        on_play: matchup_scenario(on_play: true),
        on_draw: matchup_scenario(on_play: false),
      }
      @analysis = results
    end

    private

    def matchup_scenario(on_play:)
      a_info = analyze_deck(deck_a, on_play: on_play)
      b_info = analyze_deck(deck_b, on_play: !on_play)

      win_rate_a = weighted_score(a_info, b_info)
      win_rate_b = (1.0 - win_rate_a).round(3)

      {
        archetype_a: a_info[:archetype],
        archetype_b: b_info[:archetype],
        win_rate_a: win_rate_a,
        win_rate_b: win_rate_b,
        favored: if win_rate_a > win_rate_b
                   "Deck A"
                 else
                   ((win_rate_b > win_rate_a) ? "Deck B" : "Even")
                 end,
        interaction_overlap: compare_interaction_density(a_info, b_info),
        synergy_a: a_info[:synergy_hit_rate],
        synergy_b: b_info[:synergy_hit_rate],
        notes: generate_notes(a_info, b_info, on_play: on_play),
      }
    end

    def analyze_deck(deck, on_play:)
      detector = CwCardUtils::DecklistParser::ArchetypeDetector.new(deck)
      archetype = detector.detect
      curve = deck.normalized_curve

      early = ((curve[0] || 0) + (curve[1] || 0)).round(2)
      mid   = ((curve[2] || 0) + (curve[3] || 0)).round(2)
      late  = ((curve[4] || 0) + (curve[5] || 0) + (curve[6] || 0) + (curve[7] || 0)).round(2)

      synergy_hit_rate = calc_synergy_hit_rate(deck, on_play: on_play)

      {
        archetype: archetype,
        color: detector.colors,
        early_curve: early,
        mid_curve: mid,
        late_curve: late,
        tag_ratios: detector.tag_ratios,
        tag_counts: detector.tag_counts,
        synergy_hit_rate: synergy_hit_rate,
        tribe: deck.tribe,
        format: deck.format,
      }
    end

    def calc_synergy_hit_rate(deck, on_play:)
      synergy_pairs = extract_synergy_pairs(deck)
      return 0 if synergy_pairs.empty?

      synergy_checker = CwCardUtils::SynergyProbability.new(deck, deck_size: deck.main.map(&:count).sum)

      probs = synergy_pairs.map do |pair|
        synergy_checker.prob_combo(pair, draws_by_turn(5, on_play: on_play))
      end
      (probs.sum / probs.size).round(2)
    end

    def extract_synergy_pairs(deck)
      synergy_cards = deck.main.select do |card|
        card.tags.intersect?([:synergistic_finisher, :tribal_synergy, :scaling_threat])
      end
      return [] if synergy_cards.size < 2
      synergy_cards.map(&:name).combination(2).to_a
    end

    def draws_by_turn(turn, on_play:)
      on_play ? (7 + (turn - 1)) : (7 + turn)
    end

    def weighted_score(a, b)
      # Archetype advantage
      archetype_score = case predict_matchup(a, b)
      when "Deck A (Aggro)", "Deck A (Faster curve)", "Deck A (Synergy)" then 1.0
      when "Deck B (Aggro)", "Deck B (Faster curve)", "Deck B (Synergy)" then 0.0
      else 0.5
      end

      # Curve advantage
      curve_score = if a[:early_curve] > b[:early_curve] + 0.15
        1.0
      elsif b[:early_curve] > a[:early_curve] + 0.15
        0.0
      else
        0.5
      end

      # Synergy advantage
      synergy_score = if a[:synergy_hit_rate] > b[:synergy_hit_rate] + 0.1
        1.0
      elsif b[:synergy_hit_rate] > a[:synergy_hit_rate] + 0.1
        0.0
      else
        0.5
      end

      # Interaction advantage
      interaction_score = if a[:tag_ratios][:interaction].to_f > b[:tag_ratios][:interaction].to_f + 0.05
        1.0
      elsif b[:tag_ratios][:interaction].to_f > a[:tag_ratios][:interaction].to_f + 0.05
        0.0
      else
        0.5
      end

      (
        archetype_score * WEIGHTS[:archetype] +
        curve_score * WEIGHTS[:curve] +
        synergy_score * WEIGHTS[:synergy] +
        interaction_score * WEIGHTS[:interaction]
      ).round(3)
    end

    def predict_matchup(a, b)
      return "Deck A (Aggro)" if is_aggro?(a) && is_control?(b)
      return "Deck B (Aggro)" if is_aggro?(b) && is_control?(a)
      return "Deck A (Faster curve)" if a[:early_curve] > b[:early_curve] + 0.15
      return "Deck B (Faster curve)" if b[:early_curve] > a[:early_curve] + 0.15
      return "Deck A (Synergy)" if a[:synergy_hit_rate] > b[:synergy_hit_rate] + 0.1
      return "Deck B (Synergy)" if b[:synergy_hit_rate] > a[:synergy_hit_rate] + 0.1
      "Even Matchup"
    end

    def is_aggro?(info)
      info[:archetype].downcase.include?("aggro") || info[:early_curve] > 0.5
    end

    def is_control?(info)
      info[:archetype].downcase.include?("control") || info[:late_curve] > 0.4
    end

    def compare_interaction_density(a, b)
      a_interact = a[:tag_ratios][:interaction].to_f.round(2)
      b_interact = b[:tag_ratios][:interaction].to_f.round(2)

      if (a_interact - b_interact).abs < 0.05
        "Similar density"
      elsif a_interact > b_interact
        "Deck A has more removal"
      else
        "Deck B has more removal"
      end
    end

    def generate_notes(a, b, on_play:)
      notes = []
      notes << (on_play ? "Deck A is on the play" : "Deck B is on the play")

      if a[:tribe] && b[:tribe]
        notes << "Both decks are tribal: #{a[:tribe].capitalize} vs #{b[:tribe].capitalize}"
      end

      if a[:format] != b[:format]
        notes << "Decks are from different formats: #{a[:format]} vs #{b[:format]}"
      end

      if a[:color] == b[:color]
        notes << "Color overlap may result in symmetrical strategies"
      end

      notes << "Deck A synergy hit rate: #{(a[:synergy_hit_rate] * 100).round}%"
      notes << "Deck B synergy hit rate: #{(b[:synergy_hit_rate] * 100).round}%"

      notes
    end
  end
end