<?php

namespace Inside\BCLH\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Str;
use Inside\Authentication\Models\User;
use Inside\BCLH\Facades\Pdf;
use Inside\Content\Models\Contents\Brands;
use Inside\Content\Models\Contents\Folders;
use Inside\Content\Models\Contents\Rops;
use Inside\Content\Models\Contents\Sops;
use Inside\Content\Models\Contents\Users;
use Inside\Database\Eloquent\Builder;
use Inside\Permission\Facades\Permission;

class PrepareEbook implements ShouldQueue
{
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

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

    /**
     * @var Brands|null
     */
    protected $brand;

    /**
     * @var Folders|null
     */
    protected $folder;

    /**
     * @var string|null
     */
    protected $langcode;

    public function __construct(string $userUuid, ?string $langcode, ?Brands $brand, ?Folders $folder)
    {
        $this->userUuid = $userUuid;
        $this->langcode = $langcode;
        $this->brand = $brand;
        $this->folder = $folder;
    }

    public function handle(): void
    {
        $baseFolder = $this->folder ?? Folders::query()->where('machine_name', 'sops')->where('langcode', $this->langcode)->first();

        $contents = [];

        $this->getFolderContents($baseFolder, $contents, $contents);

        $baseFolder = ! empty($this->folder) ? [
            'uuid' => $baseFolder->uuid,
            'title' => $baseFolder->title,
            'type' => 'folder',
            'hasSops' => true,
        ] : null;

        Queue::push(new GenerateEbook($this->userUuid, $this->langcode, $this->brand, $contents[0]['children'], $baseFolder), '', env('BCLH_EBOOK_QUEUE', 'bclh_ebooks'));

        $contents = null;
        $this->delete();
    }

    protected function getAllowedContent(Builder $query, User $permissionUser): void
    {
        $user = Users::query()->find($this->userUuid);
        $fields = ['brands', 'countries', 'managementModes', 'profiles'];

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

    protected function getFolderContents(Folders $folder, array &$data, array &$parent): void
    {
        $folderData = [
            'uuid' => $folder->uuid,
            'title' => $folder->title,
            'type' => 'folder',
            'hasSops' => false,
        ];

        $children = $folder->getChildrenIfExist(['sort' => 'weight:asc']);

        if (! empty($children)) {
            foreach ($children as $child) {
                if (! array_key_exists('children', $folderData)) {
                    $folderData['children'] = [];
                }

                $this->getFolderContents($child, $folderData['children'], $folderData);
            }
        }

        /** @var User $permissionUser */
        $permissionUser = User::query()->find($this->userUuid);
        $query = Sops::whereHas('folders', fn ($q) => $q->where('uuid', $folder->uuid))->where('status', 1);

        $this->getAllowedContent($query, $permissionUser);
        $sops = $query->groupBy('inside_content_sops.uuid')->orderBy('title', 'asc')->get();

        $customPerms = Permission::customList($permissionUser);

        if ($sops->count()) {
            foreach ($sops as $sop) {
                if (! $sop->status || $sop->brands->count() === 0 || ! $sop->brands->find($this->brand->uuid)) {
                    continue;
                }

                $folderData['hasSops'] = true;
                $parent['hasSops'] = true;

                $displaySop = true;
                $ropsToDisplay = [];

                $query = Rops::whereHas('sops', fn ($q) => $q->where('uuid', $sop->uuid))->where('status', 1);
                $this->getAllowedContent($query, $permissionUser);

                $rops = $query->groupBy('inside_content_rops.uuid')->orderBy('title', 'asc')->get();

                if (! empty($rops)) {
                    foreach ($rops as $rop) {
                        if (! $rop->status || ! $rop->brands->find($this->brand->uuid)) {
                            continue;
                        }

                        $ropsToDisplay[] = $rop;
                    }
                }

                if (! empty($ropsToDisplay) && ! in_array('see all sops', $customPerms)) {
                    $displaySop = false;
                }

                if ($displaySop) {
                    $documentData = Pdf::formatContentData($sop, 'sops');

                    $folderData['children'][] = $documentData;
                }

                foreach ($ropsToDisplay as $rop) {
                    $documentData = Pdf::formatContentData($rop, 'rops');

                    $folderData['children'][] = $documentData;
                }
            }
        }
        $sops = null;
        $query = Rops::whereDoesntHave('sops')->whereHas('folders', fn ($q) => $q->where('uuid', $folder->uuid))->where('status', 1);

        $this->getAllowedContent($query, $permissionUser);

        $rops = $query->groupBy('inside_content_rops.uuid')->orderBy('title', 'asc')->get();

        if ($rops->count()) {
            foreach ($rops as $rop) {
                if (! $rop->status || $rop->brands->count() === 0 || ! $rop->brands->find($this->brand->uuid)) {
                    continue;
                }

                $folderData['hasSops'] = true;
                $parent['hasSops'] = true;

                $documentData = Pdf::formatContentData($rop, 'rops');

                $folderData['children'][] = $documentData;
            }
        }
        $rops = null;

        $data[] = $folderData;
        $folderData = null;
    }
}
