<?php

namespace App\Repositories\Ecommerce\Product\Category;

use App\Models\Ecommerce\Product\Category\Category;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;

class CategoryRepository
{
    /**
     * $queryBuilder
     *
     * @var Builder
     */
    protected mixed $queryBuilder;

    /**
     * $request
     */
    protected Request $request;

    /**
     * Model
     */
    public static function model(): string
    {
        return config('ecommerce.models.category');
    }

    /**
     * Product repository
     */
    public function __construct(Request $request)
    {
        $this->queryBuilder = self::model()::query();
        $this->request = $request;
    }

    /**
     * Create new class via static method "make"
     */
    public static function make(Request $request): self
    {
        return new self($request);
    }

    /**
     * Apply Basic queries
     */
    public function applyBasicQueries(): self
    {
        $this->queryBuilder->with('media')->enabled()->ordered();

        return $this;
    }

    /**
     * Apply filters
     */
    public function applyFilters(): self
    {
        if ($this->request->filled('type')) {
            $this->filterByType();
        }

        if ($this->request->filled('group')) {
            $this->queryBuilder->where('type', $this->request->group);
        } else {
            $this->queryBuilder->where('type', '!=', 'market')->whereNot('slug', 'market');
        }

        return $this;
    }

    /**
     * Query by type
     */
    public function filterByType(): self
    {
        match ($this->request->type) {
            'root' => $this->queryBuilder->where('parent_id', null),
            'tree' => $this->queryBuilder->tree(),
        };

        return $this;
    }

    /**
     * Get the results
     */
    public function get()
    {
        $data = $this->queryBuilder->get();

        if ($this->request->type === 'tree') {
            $data = $data->toTree();
        }

        return $data;
    }

    /**
     * Get names for laravel nova
     */
    public static function getNamesForNova(): array
    {
        $names = [];
        $categories = static::model()::with('children')->where('parent_id', null)->get(['id', 'slug', 'name', 'parent_id', 'is_visible']);

        // Empty space for optional
        $names[null] = __('Select');
        foreach ($categories as $category) {
            $names[$category->id] = $category->name;

            foreach ($category->children as $child) {
                $names[$child->id] = $category->name.' / '.$child->name;
            }
        }

        return $names;
    }

    /**
     * Names with taxes (usefull for nova)
     */
    public static function namesWithTaxes(): array
    {
        return static::maskParentName(
            Category::tree()
                ->where('is_visible', true)
                ->get(['id', 'slug', 'name', 'tax_percentage', 'parent_id', 'is_visible'])
                ->toTree()
        );
    }

    /**
     * Names with taxes
     */
    public static function maskParentName($categories): array
    {
        $names = [];

        foreach ($categories as $category) {
            // Ignore if has parent
            if ($category->parent_id) {
                continue;
            }

            $names[$category->id] = sprintf('%s - %s%%', $category->name, $category->tax_percentage);

            foreach ($category->children as $child) {
                $names[$child->id] = sprintf('%s / %s - %s%%', $category->name, $child->name, $child->tax_percentage);

                foreach ($child->children as $grandChild) {
                    $names[$grandChild->id] = sprintf('%s / %s / %s - %s%%', $category->name, $child->name, $grandChild->name, $child->tax_percentage);
                }
            }
        }

        return $names;
    }

    /**
     * Filter by given "resource"
     *
     * @param  Model  $resource
     */
    public function filterBy($resource)
    {
        if (get_class($resource) === config('ecommerce.models.category')) {
            return $resource->children()->get(['id', 'parent_id', 'slug', 'name']);
        }

        if (in_array(get_class($resource), [
            config('ecommerce.models.collection'),
            config('ecommerce.models.brand'),
        ])) {
            $products = $resource->products()->distinct('products.id')->pluck('products.id');

            return $this->queryBuilder->join('product_has_relations', 'categories.id', '=', 'product_has_relations.productable_id')
                ->where('product_has_relations.productable_type', '=', 'category')
                ->whereIntegerInRaw('product_has_relations.product_id', $products)
                ->distinct('categories.id')
                ->get(['id', 'slug', 'name']);
        }

        return [];
    }
}
