# frozen_string_literal: true

module RapidDiffs
  class DiffFileHeaderComponent < ViewComponent::Base
    include ButtonHelper
    include DiffHelper

    renders_one :before_file_menu

    def initialize(diff_file:, additional_menu_items: [], environment: nil)
      @diff_file = diff_file
      @additional_menu_items = additional_menu_items
      @environment = environment
    end

    def file_title_chunks
      parts = @diff_file.file_path.split('/')
      last = parts.pop
      { path_parts: parts, filename: last }
    end

    def file_link
      helpers.project_blob_path(
        @diff_file.repository.project,
        helpers.tree_join(@diff_file.content_sha, @diff_file.new_path)
      )
    end

    def copy_path_button
      clipboard_button(
        text: @diff_file.file_path,
        gfm: "`#{@diff_file.file_path}`",
        title: _("Copy file path"),
        placement: "top",
        boundary: "viewport",
        testid: "rd-diff-file-copy-clipboard",
        class: 'rd-copy-path'
      )
    end

    def menu_items
      [
        view_file_menu_item,
        view_full_file_menu_item,
        view_on_environment_menu_item,
        rich_view_toggle,
        *@additional_menu_items
      ]
                        .compact
                        .sort_by { |item| item[:position] || Float::INFINITY }
    end

    def heading_id
      file_heading_id(@diff_file)
    end

    def root_label
      s_('RapidDiffs|Diff file controls')
    end

    def moved_title_label
      helpers.safe_format(
        s_('RapidDiffs|File moved from %{old} to %{new}'),
        old: @diff_file.old_path,
        new: @diff_file.new_path
      )
    end

    def stats_label
      return false if @diff_file.binary?

      added = @diff_file.added_lines
      removed = @diff_file.removed_lines
      counters = []
      counters << (ns_('RapidDiffs|Added %d line.', 'RapidDiffs|Added %d lines.', added) % added) if added > 0
      counters << (ns_('RapidDiffs|Removed %d line.', 'RapidDiffs|Removed %d lines.', removed) % removed) if removed > 0
      counters.join(' ')
    end

    def pretty_print_bytes(size)
      ActiveSupport::NumberHelper.number_to_human_size(size)
    end

    def view_file_menu_item
      project = @diff_file.repository.project
      file_path = @diff_file.new_path || @diff_file.old_path
      commit_sha = @diff_file.content_sha

      view_path = helpers.project_blob_path(project, helpers.tree_join(commit_sha, file_path))

      {
        text: s_('RapidDiffs|View file at %{codeStart}%{commit}%{codeEnd}'),
        messageData: {
          commit: @diff_file.content_sha[0..7]
        },
        href: view_path,
        extraAttrs: { target: '_blank' },
        position: 1
      }
    end

    def view_full_file_menu_item
      return if !@diff_file.diffable_text? || expanded? || @diff_file.rendered?

      {
        text: @diff_file.manually_expanded? ? s_('MRDiff|Show changes only') : s_('MRDiff|Show full file'),
        extraAttrs: { 'data-click': 'showFullFile', 'data-full': @diff_file.manually_expanded? },
        position: 50
      }
    end

    def expanded?
      @diff_file.fully_expanded? && !@diff_file.manually_expanded?
    end

    def view_on_environment_menu_item
      return unless @environment

      file_path = @diff_file.new_path || @diff_file.old_path
      commit_sha = @diff_file.content_sha

      environment_path = @environment.external_url_for(file_path, commit_sha)
      return unless environment_path

      {
        text: helpers.safe_format(
          s_('RapidDiffs|View on %{environment}'),
          environment: @environment.formatted_external_url
        ),
        href: environment_path,
        extraAttrs: { target: '_blank', rel: 'noopener noreferrer' },
        position: 2
      }
    end

    def rich_view_toggle
      return unless @diff_file.has_renderable?

      {
        text: @diff_file.rendered? ? s_('RapidDiffs|View plain diff') : s_('RapidDiffs|View rich diff'),
        extraAttrs: {
          'data-click': 'toggleRichView',
          'data-rendered': @diff_file.rendered?.to_json
        },
        position: 10
      }
    end
  end
end
