# frozen_string_literal: true

require 'octokit'
require 'json'
require 'google/cloud/bigquery'

class ReleaseMergeReport
  def initialize(token:, repo:, branch_prefix:)
    @token = token
    @repo = repo
    @branch_prefix = branch_prefix
  end

  def report
    branch_counts = count_merged_pull_requests_per_branch
    grouped_branch_counts = group_branch_counts(branch_counts)
    # require 'pry'
    # binding.pry
    # Print the grouped branch counts
    puts 'Branches with Merged Pull Requests:'
    grouped_branch_counts.each do |branch, count|
      puts "#{branch}: #{count}"
    end

    ENV['BQ_CREDENTIALS'] = `cat /Users/serghei.moret/.config/gcloud/application_default_credentials.json`

    export_to_bigquery(grouped_branch_counts) if ENV['BQ_CREDENTIALS']

    grouped_branch_counts
  end

  private

  def count_merged_pull_requests_per_branch
    client = Octokit::Client.new(access_token: @token)
    client.auto_paginate = true

    tags = client.tags(@repo)
    branch_info = Hash.new { |hash, key| hash[key] = { count: 0, teams: [], tribes: [] } }

    tags.each do |tag|
      next if !tag.name.match?(/^(v23|v24)\./) && !tag.name.match?(/^(23|24)\./)

      # Extract release version from the tag name
      release_version = tag.name.gsub('v', '')

      # Construct branch name with the specified prefix
      branch_name = "#{@branch_prefix}#{release_version}"

      # Count merged pull requests associated with the branch
      pull_requests = client.pull_requests(@repo, state: 'closed', sort: 'updated', direction: 'desc', base: branch_name)
                            .select(&:merged_at)

      pull_requests.each do |pr|
        branch_info[branch_name][:count] += 1

        # Extract team identifiers from the pull request labels
        teams = pr.labels.map { |label| label.name.match(/^squad:\s*(.*)$/i)&.captures }.compact.flatten
        tribes = pr.labels.map { |label| label.name.match(/^tribe:\s*(.*)$/i)&.captures }.compact.flatten
        branch_info[branch_name][:teams].push(teams)
        branch_info[branch_name][:tribes].push(tribes)
      end
      branch_info[branch_name][:count] = 0 if branch_info[branch_name].nil?
    end

    branch_info
  end

  def group_branch_counts(branch_info)
    patch_counts = Hash.new { |hash, key| hash[key] = { count: 0, teams: [], tribes: [] } }
    hotfix_counts = Hash.new { |hash, key| hash[key] = { count: 0, teams: [], tribes: [] } }

    branch_info.each do |branch, info|
      major_minor_version, patch_version = branch.match(/^#{@branch_prefix}(\d+\.\d+)(?:\.(\d+))?/)&.captures

      if patch_version.nil?
        # Branch is a patch version
        patch_counts[major_minor_version][:count] += info[:count]
        patch_counts[major_minor_version][:teams] += info[:teams]
        patch_counts[major_minor_version][:tribes] += info[:tribes]

      elsif (info[:count]).positive?
        # Branch is a hotfix version
        hotfix_counts[major_minor_version][:count] += info[:count]
        hotfix_counts[major_minor_version][:teams] += info[:teams]
        hotfix_counts[major_minor_version][:tribes] += info[:tribes]
      end
    end

    # Sum up the counts for hotfix versions within the same major and minor version
    hotfix_counts.each do |major_minor_version, hotfix_info|
      hotfix_counts[major_minor_version][:count] = hotfix_info[:count]
    end

    { patch_versions: patch_counts, hotfix_versions: hotfix_counts }
  end

  def export_to_bigquery(branch_counts)
    require 'google/cloud/bigquery'
    require 'json'
    creds = JSON.parse(ENV['BQ_CREDENTIALS'])
    bigquery = Google::Cloud::Bigquery.new(
      project_id: 'hellofresh-android',
      credentials: creds
    )
    dataset = bigquery.dataset 'github_data'

    date = DateTime.now

    branch_counts[:patch_versions].each do |branch, count|
      # Construct JSON string for teams
      teams_json = count[:teams].map { |team| "'#{team}'" }.join(',')
      tribes_json = count[:tribes].map { |tribes| "'#{tribes}'" }.join(',')

      # Construct the SQL query
      query = <<~SQL
        MERGE INTO release_merges AS target
        USING (SELECT '#{branch}' AS release, '#{@repo}' AS platform) AS source
        ON target.release = source.release AND target.platform = source.platform
        WHEN MATCHED THEN
          UPDATE SET
            target.merge_count = #{count[:count]},
            target.timestamp = '#{date}',
            target.contributors = ARRAY[#{teams_json}],
            target.contributors_tribe = ARRAY[#{tribes_json}]
        WHEN NOT MATCHED THEN
          INSERT (release, merge_count, platform, timestamp, contributors, contributors_tribe)
          VALUES ('#{branch}', #{count[:count]}, '#{@repo}', '#{date}', ARRAY[#{teams_json}], ARRAY[#{tribes_json}]);
      SQL

      # Execute the query
      dataset.query(query)

      # Update the date
      date -= 7
    end

    branch_counts[:hotfix_versions].each do |branch, count|
      # Construct JSON string for teams
      teams_json = count[:teams].map { |team| "'#{team}'" }.join(',')
      tribes_json = count[:tribes].map { |tribes| "'#{tribes}'" }.join(',')

      # Construct the SQL query
      query = <<~SQL
        MERGE INTO release_merges AS target
        USING (SELECT '#{branch}' AS release, '#{@repo}' AS platform) AS source
        ON target.release = source.release AND target.platform = source.platform
        WHEN MATCHED THEN
          UPDATE SET
            target.hotfix_count = #{count[:count]},
            target.contributors_hotfixes = ARRAY[#{teams_json}],
            target.contributors_hotfixes_tribe = ARRAY[#{tribes_json}]
        WHEN NOT MATCHED THEN
          INSERT (release, hotfix_count, platform, contributors_hotfixes, contributors_hotfixes_tribe )
          VALUES ('#{branch}', #{count[:count]}, '#{@repo}', ARRAY[#{teams_json}], ARRAY[#{tribes_json}]);
      SQL

      # Execute the query
      dataset.query(query)
    end
  end
end