require 'pathname'
require 'thor'
require 'tmpdir'
require 'debci'
require 'debci/amqp'
require 'debci/html'
require 'debci/job'

module Debci
  class Collector
    def run
      Debci.log "debci collector started"
      channel = Debci::AMQP.amqp_channel
      queue = Debci::AMQP.results_queue
      queue.subscribe(manual_ack: true) do |delivery_info, _properties, payload|
        Dir.mktmpdir do |dir|
          receive_payload(dir, payload)
        end
        channel.acknowledge(delivery_info.delivery_tag, false)
      end
      begin
        loop { sleep 1 }
      rescue Interrupt
        Debci.log "debci collector stopped"
      end
    end

    def receive_payload(dir, payload)
      if payload.nil? || payload.empty?
        Debci.warn("W: received empty payload, ignoring")
        return
      end

      unless File.directory?(dir)
        Debci.warn("W: #{dir} is not a directory, ignoring")
        return
      end

      Dir.chdir(dir) do
        results = Pathname('results.tar.gz')
        results.open('wb') do |f|
          f.write(payload)
        end
        begin
          Debci.run('tar', 'xaf', results.to_s)
        rescue Debci::CommandFailed
          Debci.warn("W: received invalid tarball data")
        end
        results.unlink
      end

      exitcodes = Pathname(dir).glob('**/exitcode')
      return if exitcodes.empty?

      receive(exitcodes.first.parent)
    end

    def receive(directory)
      job = Debci::Job.receive(directory)

      if job.nil?
        Debci.log("receiving from #{directory} failed associating a job")
      else
        data = {
          package: job.package.name,
          suite: job.suite,
          arch: job.arch,
          backend: job.backend,
          status: job.status,
          duration_human: job.duration_human,
          run_id: job.run_id,
        }
        Debci.log('%<package>s %<suite>s/%<arch>s/%<backend>s (%<run_id>s) %<status>s %<duration_human>s' % data)
      end
    end

    class CLI < Thor
      desc 'run', 'Runs the debci results collector'
      def start
        Collector.new.run
      end
      default_task :start
    end
  end
end
