module Fastlane
  module Actions
    class SubtreeStatusAction < Action
      def self.run(params)
        subtree = params[:subtree]
        repo_name = params[:repo]
        branch = params[:branch]

        # Build full repo URL from repo name
        repo_url = Github.repo_url(repo: repo_name)

        UI.important("Checking status for subtree `#{subtree}`...")
        head_sha = Actions.sh("git ls-remote #{repo_url} #{branch} | awk '{print $1}'", log: true).strip
        last_merge_sha = Actions.sh("git log -1 --merges --grep='Merge commit.*' --format='%H' #{subtree}/", log: true).strip

        if last_merge_sha
          last_updated = Actions.sh("git log -1 --relative-date --format='%cd' #{last_merge_sha}", log: true).strip
          last_merge_message = Actions.sh("git log -1 --format='%s' #{last_merge_sha}", log: true).strip
          match = last_merge_message.match(/Merge commit '([0-9a-f]{40})'/)
          unless match
            UI.crash!("Failed to parse merge commit message: #{last_merge_message}")
          end
          current_sha = match.captures.first
          commits_to_pull = if current_sha != head_sha
            Actions.sh("git fetch #{repo_url} #{branch}", log: true)
            Actions.sh("git rev-list #{current_sha}..FETCH_HEAD", log: true).strip.split("\n")
          else
            []
          end

          commits_to_push = Actions.sh("git log #{last_merge_sha ? "#{last_merge_sha}..HEAD" : ""} --follow --format='%H' #{subtree}/", log: true).strip.split("\n") rescue []

          status_messages = []
          unless commits_to_pull.empty?
            status_messages << "#{commits_to_pull.count} commit(s) behind"
          end
          unless commits_to_push.empty?
            status_messages << "#{commits_to_push.count} commit(s) ahead"
          end
          status = status_messages.empty? ? "up to date".green : status_messages.join(", ").yellow
        else
          status = "not initialized".yellow
        end

        # Check for changed files
        changed_files = other_action.github_changed_files.select { |file| file.start_with?("#{subtree}/") }

        # Check for any open PRs
        pr_number = params[:pr_number]
        pr_label = params[:pr_label]
        pr_head_sha = nil
        if pr_number
          pr = Github.lookup_pr_by_number(number: pr_number, fields: "number,url,title,body,author,headRefName,headRefOid")
          unless pr
            UI.user_error!("PR ##{pr_number} not found")
          end
          pr_head_sha = pr["headRefOid"]
          subtree_pr_head_ref = "#{pr_label}-#{subtree}-#{pr["headRefName"]}"
          subtree_pr_title = "#{pr["title"]} [#{pr_label}]"
          subtree_pr_body = "_This PR was automatically created from mobile repo PR #{pr["url"]} by @#{pr["author"]["login"]}_\n\n---\n\n#{pr["body"]}"
          subtree_pr = Github.lookup_pr_by_head_ref(head_ref: subtree_pr_head_ref, repo: repo_name, fields: "number,url,headRefOid")
        end

        result = {
          subtree: subtree,
          ok: commits_to_push.count == 0,
          status: status,
          repo: repo_name,
          branch: branch,
          head_sha: head_sha,
          current_sha: current_sha,
          last_updated: last_updated,
          last_merge_sha: last_merge_sha,
          commits_to_pull: commits_to_pull,
          commits_to_push: commits_to_push,
          changed_files: changed_files,
          changed_files_count: changed_files.count,
          pr_head_ref: subtree_pr_head_ref,
          pr_head_sha: subtree_pr ? subtree_pr["headRefOid"] : nil,
          pr_url: subtree_pr ? subtree_pr["url"] : nil,
          pr_number: subtree_pr ? subtree_pr["number"] : nil,
          pr_title: subtree_pr_title,
          pr_body: subtree_pr_body,
        }

        FastlaneCore::PrintTable.print_values(
          config: result,
          hide_keys: [:commits_to_pull, :commits_to_push, :changed_files, :pr_title, :pr_body, :pr_url],
          title: "Status for subtree '#{subtree}'"
        )

        if pr_head_sha
          UI.message("Creating status check for subtree '#{subtree}'...")
          description = subtree_pr ? "Subtree PR is not yet merged: #{repo_name}/pulls/#{pr_number}" : result[:status].gsub(/\e\[[0-9;]*m/, '')
          Actions.sh(
            "gh api repos/#{Github.org}/#{Github.repo}/statuses/#{pr_head_sha} " \
            "--method POST " \
            "--field state=#{result[:ok] ? "success" : "error"} " \
            "--field context='Subtree / #{subtree}' " \
            "--field description='#{description.length > 140 ? "#{description[0..136]}..." : description}' " \
            "--field target_url='#{result[:pr_url] || Github.repo_url(repo: result[:repo])}'",
            log: true
          )
          UI.success("Successfully created status check for subtree '#{subtree}'")
        end

        result
      end

      def self.description
        "Get status information for a given subtree"
      end

      def self.authors
        ["Suno"]
      end

      def self.return_value
        "Hash containing detailed subtree status"
      end

      def self.available_options
        [
          FastlaneCore::ConfigItem.new(
            key: :repo,
            description: "Repository name (e.g., 'app-android' - org 'suno-ai' will be added automatically)",
            type: String,
            verify_block: proc do |value|
              UI.user_error!(':repo option cannot be empty') if value.to_s.empty?
            end
          ),
          FastlaneCore::ConfigItem.new(
            key: :branch,
            description: "The remote branch to sync with",
            type: String,
            verify_block: proc do |value|
              UI.user_error!(':branch option cannot be empty') if value.to_s.empty?
            end
          ),
          FastlaneCore::ConfigItem.new(
            key: :subtree,
            description: "Subtree path (e.g., 'android', 'ios')",
            type: String,
            verify_block: proc do |value|
              UI.user_error!(':subtree option cannot be empty') if value.to_s.empty?
            end
          ),
          FastlaneCore::ConfigItem.new(
            key: :pr_number,
            description: "PR number from mobile repo to sync (defaults to GITHUB environment if available)",
            type: String,
            optional: true,
            verify_block: proc do |value|
              UI.user_error!(':pr_number option cannot be empty') if value.to_s.empty?
            end
          ),
          FastlaneCore::ConfigItem.new(
            key: :pr_label,
            description: "Label to use for subtree PRs",
            type: String,
            default_value: "mobile-repo-sync",
            verify_block: proc do |value|
              UI.user_error!(':pr_label option cannot be empty') if value.to_s.empty?
            end
          ),
        ]
      end

      def self.is_supported?(platform)
        true
      end
    end
  end
end
