<?php

namespace Amranidev\MicroBus\Sqs;

use Aws\Sqs\SqsClient;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Queue\Jobs\SqsJob as AbstractSqsJob;

class SqsJob extends AbstractSqsJob
{
    use Macroable;

    /**
     * Job handler class.
     *
     * @var string
     */
    protected $handler;

    /**
     * SqsJob constructor.
     *
     * @param $container
     * @param \Aws\Sqs\SqsClient $sqs
     * @param array              $job
     * @param string             $connectionName
     * @param string             $queue
     * @param $handler
     */
    public function __construct($container, SqsClient $sqs, array $job, string $connectionName, string $queue, $handler)
    {
        parent::__construct($container, $sqs, $job, $connectionName, $queue);
        $this->handler = $handler;

        $this->setLaravelJobUuid();
    }

    /**
     * Get the decoded body of the job.
     *
     * @return array
     */
    public function payload()
    {
        $payload = parent::payload();

        $payload['job'] = $this->handler;
        $payload['data'] = $payload['Message'];

        return $payload;
    }

    /**
     * Set the 'uuid' field required by some parts of the Laravel Queue system.
     *
     * For some cases (e.g. the 'database-uuids' failed jobs driver), Laravel Queue system needs a 'uuid' field in the raw body
     * of the job. The original Laravel Queue SqsJob includes this UUID in the AWS SQS 'Body' at the job dispatch time, which is
     * not possible for micro-bus because the AWS SQS 'Body' is generated by AWS SNS rather than by this PHP code.
     * This function gets this UUID back from the AWS SQS 'MessageAttributes' and copies it in the correct place for the Laravel
     * Queue system to be able to use it.
     *
     * Note: It would have been cleaner to integrate this in the payload() method, however the 'database-uuids' failed jobs driver of
     *       Laravel reads it directly from the raw body rather than from the Job's payload() or uuid() method.
     */
    private function setLaravelJobUuid()
    {
        // First we will need to check if the MessageAttributes exists.
        if (!array_key_exists('MessageAttributes', $this->payload())) {
            return;
        }

        $snsMessageAttributes = $this->payload()['MessageAttributes'];

        if (isset($snsMessageAttributes)
            && isset($snsMessageAttributes['MICRO_BUS.JOB_UUID'])
            && isset($snsMessageAttributes['MICRO_BUS.JOB_UUID']['Value'])) {
            $jobBody = json_decode($this->job['Body'], true);
            $jobBody['uuid'] = $snsMessageAttributes['MICRO_BUS.JOB_UUID']['Value'];
            $this->job['Body'] = json_encode($jobBody); // $this->job['Body'] is what is returned by 'getRawBody()', which is then used by Laravel to read the 'uuid' field
        }
    }
}
