# frozen_string_literal: true

module Processors
  ##
  # CharacterProcessor processes an array of character data and creates GridCharacter records.
  #
  # @example
  #   processor = Processors::CharacterProcessor.new(party, transformed_characters_array)
  #   processor.process
  class CharacterProcessor < BaseProcessor
    def initialize(party, data, type = :normal, options = {})
      super(party, data, options)
      @party = party
      @data = data
    end

    ##
    # Processes character data.
    #
    # Iterates over each character hash in +data+ and creates a new GridCharacter record.
    # Expects each character hash to include keys such as :id, :position, :uncap, etc.
    #
    # @return [void]
    def process
      unless @data.is_a?(Hash)
        Rails.logger.error "[CHARACTER] Invalid data format: expected a Hash, got #{@data.class}"
        return
      end

      unless @data.key?('deck') && @data['deck'].key?('npc')
        Rails.logger.error '[CHARACTER] Missing npc data in deck JSON'
        return
      end

      @data = @data.with_indifferent_access
      characters_data = @data.dig('deck', 'npc')

      grid_characters = process_characters(characters_data)
      grid_characters.each do |grid_character|
        begin
          grid_character.save!
        rescue ActiveRecord::RecordInvalid => e
          Rails.logger.error "[CHARACTER] Failed to create GridCharacter: #{e.record.errors.full_messages.join(', ')}"
        end
      end

    rescue StandardError => e
      raise e
    end

    private

    def process_characters(characters_data)
      characters_data.map do |key, raw_character|
        next if raw_character.nil? || raw_character['param'].nil? || raw_character['master'].nil?

        position = key.to_i - 1

        # Find the Character record by its granblue_id.
        character_id = raw_character.dig('master', 'id')
        character = Character.find_by(granblue_id: character_id)

        unless character
          Rails.logger.error "[CHARACTER] Character not found with id #{character_id}"
          next
        end

        # The deck doesn't have Awakening data, so use the default
        awakening = Awakening.where(slug: 'character-balanced').first
        grid_character = GridCharacter.create(
          party_id: @party.id,
          character_id: character.id,
          uncap_level: raw_character.dig('param', 'evolution').to_i,
          transcendence_step: raw_character.dig('param', 'phase').to_i,
          position: position,
          perpetuity: raw_character.dig('param', 'has_npcaugment_constant'),
          awakening: awakening
        )

        grid_character
      end.compact
    end

    # Converts a value to a boolean.
    def parse_boolean(val)
      val.to_s.downcase == 'true'
    end
  end
end
