# frozen_string_literal: true

module Granblue
  module Downloaders
    # Downloads character image assets from the game server in different sizes and variants.
    # Handles character-specific variants like base art, uncap art, and transcendence art.
    #
    # @example Download images for a specific character
    #   downloader = CharacterDownloader.new("3040001000", storage: :both)
    #   downloader.download
    #
    # @note Character images come in multiple variants (_01, _02, etc.) based on uncap status
    # @note Supports FLB (5★) and ULB (6★) art variants when available
    class CharacterDownloader < BaseDownloader
      # Downloads images for all variants of a character based on their uncap status.
      # Overrides {BaseDownloader#download} to handle character-specific variants.
      #
      # @return [void]
      # @note Skips download if character is not found in database
      # @note Downloads FLB/ULB variants only if character has those uncaps
      # @see #download_variants
      def download
        character = Character.find_by(granblue_id: @id)
        return unless character

        download_variants(character)
      end

      private

      # Downloads all variants of a character's images
      # @param character [Character] Character model instance to download images for
      # @return [void]
      # @note Only downloads variants that should exist based on character uncap status
      def download_variants(character)
        # All characters have 01 and 02 variants
        variants = %W[#{@id}_01 #{@id}_02]

        # Add FLB variant if available
        variants << "#{@id}_03" if character.flb

        # Add ULB variant if available
        variants << "#{@id}_04" if character.ulb

        log_info "Downloading character variants: #{variants.join(', ')}" if @verbose

        variants.each do |variant_id|
          download_variant(variant_id)
        end
      end

      # Downloads a specific variant's images in all sizes
      # @param variant_id [String] Character variant ID (e.g., "3040001000_01")
      # @return [void]
      def download_variant(variant_id)
        log_info "-> #{variant_id}" if @verbose
        return if @test_mode

        SIZES.each_with_index do |size, index|
          path = download_path(size)
          url = build_variant_url(variant_id, size)
          process_download(url, size, path, last: index == SIZES.size - 1)
        end
      end

      # Builds URL for a specific variant and size
      # @param variant_id [String] Character variant ID
      # @param size [String] Image size variant ("main", "grid", or "square")
      # @return [String] Complete URL for downloading the image
      def build_variant_url(variant_id, size)
        directory = directory_for_size(size)
        "#{@base_url}/#{directory}/#{variant_id}.jpg"
      end

      # Gets object type for file paths and storage keys
      # @return [String] Returns "character"
      def object_type
        'character'
      end

      # Gets base URL for character assets
      # @return [String] Base URL for character images
      def base_url
        'http://gbf.game-a.mbga.jp/assets/img/sp/assets/npc'
      end

      # Gets directory name for a size variant
      # @param size [String] Image size variant
      # @return [String] Directory name in game asset URL structure
      # @note Maps "main" -> "f", "grid" -> "m", "square" -> "s"
      def directory_for_size(size)
        case size.to_s
        when 'main' then 'f'
        when 'grid' then 'm'
        when 'square' then 's'
        end
      end
    end
  end
end
