# frozen_string_literal: true

module ReleaseTools
  module Security
    module ReleasePreparation
      class GenerateBlogPost
        include ReleaseTools::Security::IssueHelper
        include ReleaseTools::Security::MergeRequestHelper
        include ::SemanticLogger::Loggable

        def initialize
          @blog_post = PatchRelease::BlogPost::MergeRequestFactory.create(
            patch_coordinator: ReleaseTools::PatchRelease::Coordinator.new,
            security_fixes: ReleaseTools::Security::IssueCrawler.new.related_security_issues
          )
        end

        def execute
          if SharedStatus.dry_run?
            logger.info("Printing blog post for patch release")

            puts blog_post.generate_blog_content
            return
          end

          if blog_post.exists?
            logger.info('patch release blog post exists')

            add_comment_on_security_blog_post
          else
            logger.info('Creating patch release blog post')

            blog_post.create
            notify_release_managers
            notify_app_sec_release_managers
            send_success_slack_notification
          end
        rescue StandardError => ex
          logger.fatal(failure_message, error: ex)

          send_failed_slack_notification

          raise
        end

        private

        attr_reader :blog_post

        def notify_release_managers
          Retriable.with_context(:api) do
            ReleaseTools::GitlabClient.create_merge_request_comment(
              ReleaseTools::Project::WWWGitlabCom.security_path,
              blog_post.iid,
              "@gitlab-org/release/managers this is the security blog post for #{security_tracking_issue.web_url}."
            )
          end
        end

        def notify_app_sec_release_managers
          ReleaseTools::Slack::Security::AppSecNotifier
            .new(issuable: blog_post, issue_type: 'patch_blog_post')
            .send_notification
        end

        def add_comment_on_security_blog_post
          logger.info('Posting a new version of the blog post on the security merge request', merge_request: security_blog_merge_request.web_url)

          return if SharedStatus.dry_run?

          blog_content = blog_post
            .generate_blog_content
            .split('-->')
            .last # Return the content not the headers

          comment_content = <<~HEADER
            :mega: **A new version of the blog post has been generated**
            _________________________________________________

            #{blog_content}
          HEADER

          Retriable.with_context(:api) do
            GitlabClient.create_merge_request_comment(
              ReleaseTools::Project::WWWGitlabCom.security_path,
              security_blog_merge_request.iid,
              comment_content
            )
          end
        end

        def send_failed_slack_notification
          ReleaseTools::Slack::ReleaseJobEndNotifier.new(
            job_type: 'Generate blog post',
            status: :failed,
            release_type: :patch
          ).send_notification
        end

        def send_success_slack_notification
          ReleaseTools::Slack::ReleaseJobEndNotifier.new(
            job_type: 'Generate blog post',
            status: :success,
            release_type: :patch,
            extra_string: "Blog MR: #{blog_post.url}"
          ).send_notification
        end

        def failure_message
          <<~MSG
            Generating patch release blog post failed. If this job continues to fail,
            the blog post can be created by executing the `release:patch_blog_post` rake task.
          MSG
        end
      end
    end
  end
end
