<?php

namespace Inside\DESK\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
use Inside\Content\Models\Contents\NewsCategories;
use Inside\Content\Models\Contents\Users;
use Inside\DESK\Facades\UrlSigner;
use Inside\DESK\Mail\Newsletter;
use Inside\DESK\Models\NewsletterStatistic;
use Inside\Permission\Models\User;
use Inside\Slug\Facades\ContentUrlGenerator;

/**
 * Class SendNewsletter
 *
 * @category Class
 * @package  Inside\DESK\Jobs\SendNewsletter
 * @author   Maecia <technique@maecia.com>
 * @license  http://www.gnu.org/copyleft/gpl.html GNU General Public License
 * @link     http://www.maecia.com/
 */
class SendNewsletter implements ShouldQueue
{
    use InteractsWithQueue;
    use Queueable;

    /**
     * @var Users
     */
    protected $user;

    /**
     * @var string
     */
    protected $startDate;

    /**
     * @var bool
     */
    protected $test;

    /**
     * PublishContent constructor.
     *
     * @param Users $user
     * @param string $startDate
     * @param bool $test
     */
    public function __construct(Users $user, string $startDate, bool $test = false)
    {
        $this->user = $user;
        $this->startDate = $startDate;
        $this->test = $test;
    }

    /**
     *
     */
    public function handle(): void
    {
        $fields = ['brands', 'countries', 'management_modes', 'profiles'];
        $contentTypes = ['news', 'career_infos', 'memorandums', 'forms'];
        $today = $this->startDate.' 00:00:00';

        $user = $this->user;

        if (DB::table('desk_newsletters_sent')->where('date_sent', $today)->where('user_uuid', $user->uuid)->exists()) {
            return;
        }

        $today = $this->startDate.' '.env('DESK_NEWSLETTERS_BATCH_START', '12:00').':00';
        $date = date('Y-m-d H:i:s', (int)strtotime($today.' -7 days'));

        /** @var User $permissionUser */
        $permissionUser = User::query()->find($user->uuid);
        $newsletterCategories = NewsCategories::query()->where('langcode', $user->langcode)->orderBy('title')->get();

        $newsletterContents = [];

        foreach ($newsletterCategories as $category) {
            $newsletterContents[$category->uuid] = [
                'title' => $category->title,
                'contents' => [],
            ];
        }

        $hasContents = false;

        foreach ($contentTypes as $contentType) {
            $query = call_user_func(type_to_class($contentType).'::query')->where('status', 1)->where('published_at', '>=', $date)->where('published_at', '<=', $today);

            if ($contentType === 'forms') {
                $query->where('form_type', 'surveys');
            }

            if (!$permissionUser->hasAnyRole('super_administrator')) {
                foreach ($fields as $field) {
                    $references = $user->{Str::studly($field)}->pluck(['uuid'])->toArray();

                    $query->join('inside_pivots AS inside_pivots_'.$field, function ($join) use ($contentType, $field, $references) {
                        $join->on('inside_pivots_'.$field.'.parent_uuid', '=', 'inside_content_'.$contentType.'.uuid')
                            ->where(function ($subQuery) use ($field, $references) {
                                $subQuery->whereIn('inside_pivots_'.$field.'.related_uuid', $references);
                            });
                    });
                }
            }

            $contents = $query->groupBy('inside_content_'.$contentType.'.uuid')->get();

            foreach ($contents as $content) {
                $categories = $content->newsCategories;

                if ($categories->count() === 0) {
                    continue;
                }

                foreach ($categories as $category) {
                    if (!array_key_exists($category->uuid, $newsletterContents)) {
                        continue;
                    }

                    $hasContents = true;

                    $formattedContent = [
                        'uuid' => $content->uuid,
                        'type' => $content->content_type,
                        'title' => $content->title,
                        'timestamp' => $content->published_at,
                        'image' => in_array($content->content_type, ['news', 'forms']) ? (newsletter_signed_url($user, null, $content, get_stylized_image_url($content, 'image', 'thumbnail', true), '') . '?' . time()) : env('APP_URL') . '/vendor/maecia/desk-back/resources/assets/img/newsletter/' . $user->langcode . '/' . $content->content_type . '.png',
                        'brands' => [],
                        'slug' => UrlSigner::signedRoute(
                            'desk.newsletters.clicked',
                            [
                                'newsletterDate' => strtotime($today),
                                'userUuid' => $user->uuid,
                                'redirect' => ContentUrlGenerator::generateUrl($content),
                            ]
                        ),
                    ];

                    $brands = $content->brands;

                    foreach ($brands as $brand) {
                        $formattedContent['brands'][] = [
                            'uuid' => $brand->uuid,
                            'title' => $brand->title,
                            'image' => newsletter_signed_url($user, null, $brand, get_stylized_image_url($brand, 'image', 'none', true), '').'?'.time(),
                        ];
                    }

                    $newsletterContents[$category->uuid]['contents'][] = $formattedContent;
                }
            }
        }

        foreach ($newsletterCategories as $category) {
            uasort($newsletterContents[$category->uuid]['contents'], function ($a, $b) {
                if ($a['timestamp'] === $b['timestamp']) {
                    return 0;
                }

                return ($a['timestamp'] > $b['timestamp']) ? -1 : 1;
            });
        }

        if ($hasContents) {
            Mail::to($user->email)->send(new Newsletter($newsletterContents, $user->langcode, $today, $this->test, $user->uuid));
            NewsletterStatistic::firstOrCreate([
                'newsletter_date' => $today,
                'user_uuid' => $user->uuid,
                'statistic_type' => NewsletterStatistic::TYPE_SENT,
            ]);
        }

        if (!$this->test) {
            DB::table('desk_newsletters_sent')->insert([
                'date_sent' => $today,
                'user_uuid' => $user->uuid,
                'langcode' => $user->langcode,
            ]);
        }
    }
}
