# frozen_string_literal: true

require 'yaml'
begin
  require 'tty-markdown'
rescue LoadError
end

module GDK
  class Announcement
    VALID_FILENAME_REGEX = /\A\d{4}_\w+\.yml/

    attr_reader :header, :body

    FilenameInvalidError = Class.new(StandardError)

    def self.from_file(filepath)
      yaml = YAML.safe_load(filepath.read)
      new(filepath, yaml['header'], yaml['body'])
    end

    def initialize(filepath, header, body)
      @filepath = Pathname.new(filepath)
      raise FilenameInvalidError unless filename_valid?

      @header = header
      @body = body
      read_cache_file_contents!
    end

    def cache_announcement_rendered
      read_cache_file_contents!

      cache_file_contents[announcement_unique_identifier] = true

      update_cached_file
    end

    def render?
      cache_file_contents[announcement_unique_identifier] != true
    end

    def render
      return unless render?

      display
      cache_announcement_rendered
    end

    private

    attr_reader :filepath
    attr_accessor :cache_file_contents

    def filename_valid?
      filepath.basename.to_s.match?(VALID_FILENAME_REGEX)
    end

    def config
      GDK.config
    end

    def display
      if defined?(TTY::Markdown)
        options = { width: 80, color: GDK::Output.colorize? ? :always : :never }
        GDK::Output.puts TTY::Markdown.parse("**#{header}**", **options)
        GDK::Output.puts TTY::Markdown.parse("***", **options)
        GDK::Output.puts TTY::Markdown.parse(body, **options)
        return
      end

      GDK::Output.info(header)
      GDK::Output.divider
      GDK::Output.puts(body)
    end

    def update_cached_file
      config.__cache_dir.mkpath
      cache_file.open('w') { |f| f.write(cache_file_contents.to_yaml) }
    end

    def announcement_unique_identifier
      @announcement_unique_identifier ||= filepath.basename.to_s[0..3]
    end

    def cache_file
      @cache_file ||= config.__cache_dir.join('.gdk-announcements.yml')
    end

    def read_cache_file_contents!
      @cache_file_contents = cache_file.exist? ? YAML.safe_load(cache_file.read) : {}
    end
  end
end

if defined?(TTY::Markdown)
  module GDKMarkdown
    # Always use blue color instead to account for contrast issues in highlighted code.
    # https://gitlab.com/gitlab-org/gitlab-development-kit/-/issues/2301
    def convert_codespan(element, _opts)
      @pastel.blue(element.value)
    end
  end

  TTY::Markdown::Converter.prepend(GDKMarkdown)
end
