<?php

namespace Inside\BCLH\Repository;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Inside\Content\Models\Content;
use Inside\Content\Models\Contents\Rops;
use Inside\Content\Models\Contents\Sops;

class ExportableContentRepository
{
    private const PENDING_WORKFLOW_STATUS = 2;

    private const ACTIVE_STATUS = 1;

    private array $return = [];

    private array $groupedRops = [];

    public function getExportableSopsAndRops(array $filters): array
    {
        $types = ! empty($filters['type']) ? explode(',', $filters['type']) : ['rops', 'sops', 'procedures', 'documents'];
        collect($types)->each(function ($type) use ($filters) {
            $withRelations = [
                'brands:uuid,code',
                'users:uuid,email',
                'countries:uuid,code',
                'profiles:uuid,code',
                'folders:uuid,title',
                'managementModes:code',
            ];

            if ($type == 'rops') {
                $withRelations[] = 'sops:uuid,uuid_host,title';
            } elseif ($type == 'procedures') {
                $withRelations = [
                    'brands:uuid,code',
                    'users:uuid,email',
                    'countries:uuid,code',
                    'profiles:uuid,code',
                ];
            } elseif ($type == 'documents') {
                $withRelations = [
                    'brands:uuid,code',
                    'countries:uuid,code',
                    'profiles:uuid,code',
                    'folders:uuid,title',
                    'managementModes:code',
                ];
            }
            $langcode = $filters['langcode'] ?? 'en';
            $query = type_to_class($type)::with($withRelations)->where([
                'status' => $filters['status'] ?? 1,
                'langcode' => $langcode,
            ]);

            if (! empty($filters['workflow']) && ! empty($filters['workflow']['status:eq'])) {
                $query->whereHas('workflow', function (Builder $builder) use ($filters) {
                    $builder->where('status', '=', $filters['workflow']['status:eq']);
                });
            } else {
                $query->whereDoesntHave('workflow', function (Builder $builder) {
                    $builder->where('status', '=', self::PENDING_WORKFLOW_STATUS);
                });
            }

            if (! empty($filters['uuid:in'])) {
                $query->whereIn('uuid', $filters['uuid:in']);
            }

            collect(['brands', 'countries'])->each(function ($relation) use (&$query, $filters) {
                if (! empty($filters[$relation])) {
                    $query->whereHas($relation, fn ($builder) => $builder
                        ->whereIn('uuid', $filters[$relation]))
                        ->where('status', self::ACTIVE_STATUS);
                }
            });
            $collection = $query->get();
            $this->addCollection($collection, $type);
        });

        $merged = collect();
        // Exporter les rop lié à un sop en dessous de ces derniers
        if (isset($this->return['sops']) && $this->return['sops']->isNotEmpty()) {
            $this->return['sops']->each(function ($sop) use (&$merged) {
                $merged->push($sop);
                if (isset($this->return['rops']) && $this->return['rops']->has($sop['uuid_host'])) {
                    $merged = $merged->merge($this->return['rops']->get($sop['uuid_host']));
                }
            });
        }

        if (isset($this->return['rops']) && $this->return['rops']->isNotEmpty()) {
            $rops = (isset($this->return['sops']) && $this->return['sops']->isEmpty()) ? $this->return['rops'] : $this->return['rops']->get('null');
            $merged = $merged->merge($rops);
        }

        if (isset($this->return['procedures']) && $this->return['procedures']->isNotEmpty()) {
            $merged = $merged->merge($this->return['procedures']);
        }

        if (isset($this->return['documents']) && $this->return['documents']->isNotEmpty()) {
            $merged = $merged->merge($this->return['documents']);
        }

        return $merged->toArray();
    }

    private function addCollection(Collection $collection, string $type): void
    {
        $forrmatteCollection = $collection->map(fn ($data) => [
            'uuid_host' => $data->uuid_host,
            'content_type' => $type,
            'title' => $data->title,
            'brands' => $this->getCodes($data, 'brands'),
            'countries' => $this->getCodes($data, 'countries'),
            'management_modes' => $this->getCodes($data, 'managementModes'),
            'profiles' => $this->getCodes($data, 'profiles'),
            'contact' => $data->users?->pluck('email')->implode(','),
            'folder' => $data->folders?->pluck('title')->implode(','),
            'parent' => $data->sops?->pluck('title')->implode(','),
            'parent_uuid_host' => empty($data->sops?->pluck('uuid_host')->implode('')) ? 'null' : $data->sops->pluck('uuid_host')->implode(''),
        ]);

        if ($type == 'rops') {
            $this->return[$type] = $forrmatteCollection->groupBy('parent_uuid_host')->map(function ($items) {
                return $items->map(function ($item) {
                    return collect($item)->except('parent_uuid_host');
                });
            });
        } else {
            $this->return[$type] = $forrmatteCollection->map(function ($item) {
                return collect($item)->except('parent_uuid_host');
            });
        }
    }

    private function getCodes(Content $content, string $attribute): string
    {
        $max = call_user_func(type_to_class($attribute).'::query')
            ->where('langcode', '=', $content->langcode)
            ->count();

        if ($content->{$attribute}->count() === $max) {
            return 'all';
        }

        return $content->{$attribute}->pluck('code')->implode(',');
    }
}
