# frozen_string_literal: true

module RedmineUxToolkit
  module Services
    module SlaLight
      module_function

      def enabled?(settings = Setting.plugin_redmine_ux_toolkit || {})
        settings.fetch('enable_sla_light', '0').to_s == '1'
      end

      def hints_for(issue, now: Time.current, settings: Setting.plugin_redmine_ux_toolkit || {})
        return [] unless enabled?(settings)
        return [] unless issue&.persisted?
        return [] if issue_closed?(issue)

        if paused?(issue, settings)
          return [{type: :paused, at: nil}]
        end

        hints = []
        first_response_due_at = due_at(issue.created_on, hours_setting(settings, 'sla_light_first_response_hours', 8))

        unless first_response_at(issue)
          hints << due_hint(:first_response, first_response_due_at, now)
        end

        resolution_due_at = due_at(issue.created_on, hours_setting(settings, 'sla_light_resolution_hours', 72))
        hints << due_hint(:resolution, resolution_due_at, now)

        hints.compact
      end

      def active_for?(issue, settings = Setting.plugin_redmine_ux_toolkit || {})
        enabled?(settings) &&
          issue&.persisted? &&
          !issue_closed?(issue) &&
          !paused?(issue, settings)
      end

      def paused?(issue, settings = Setting.plugin_redmine_ux_toolkit || {})
        pause_status_ids(settings).include?(issue.status_id.to_i)
      end

      def first_response_at(issue)
        Array(issue.journals).select { |journal| response_journal?(journal, issue.author_id) }
                             .min_by(&:created_on)
                             &.created_on
      end

      def response_journal?(journal, author_id)
        journal.notes.to_s.strip.present? &&
          journal.user_id.present? &&
          journal.user_id.to_i != author_id.to_i
      end

      def due_hint(kind, due_at, now)
        type = now > due_at ? :"#{kind}_overdue" : :"#{kind}_due"
        {type: type, at: due_at}
      end

      def due_at(start_time, hours)
        start_time + hours.hours
      end

      def hours_setting(settings, key, fallback)
        value = settings.fetch(key, fallback.to_s).to_i
        value.positive? ? value : fallback
      end

      def pause_status_ids(settings)
        Array(settings['sla_light_pause_status_ids']).map(&:to_i)
      end

      def issue_closed?(issue)
        return issue.closed? if issue.respond_to?(:closed?)

        issue.status&.is_closed?
      end
    end
  end
end
