<?php

namespace App\Domains\Tenant\Resources;

use App\Domains\Attachable\Models\Attachment;
use App\Domains\Catalog\Models\Category;
use App\Domains\Menu\Models\Menu;
use App\Domains\Tenant\Models\Tenant;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;

/**
 * @mixin Tenant
 */
class TenantResource extends JsonResource
{
    /**
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'codigo' => $this->codigo,
            'nombre' => $this->nombre,
            'dominio' => $this->dominio,
            'primary_color' => $this->primary_color,
            'secondary_color' => $this->secondary_color,
            'danger_color' => $this->danger_color,
            'success_color' => $this->success_color,
            'header_bg_color' => $this->header_bg_color,
            'footer_bg_color' => $this->footer_bg_color,
            'website_type_code' => $this->website_type_code,
            'extras' => $this->whenLoaded(
                'websiteExtras',
                fn () => $this->websiteExtras
                    ->filter(fn ($extra) => $extra->is_enabled)
                    ->mapWithKeys(fn ($extra) => [
                        $extra->websiteTypeExtra->codigo => $this->formatExtraConfig(
                            $extra->resolvedConfig()
                        ),
                    ])
            ),
            // 1 day
            'header_logo' => $this->headerLogo?->getTemporaryUrl(1440),
            'footer_logo' => $this->footerLogo?->getTemporaryUrl(1440),
            'search_product_layout' => $this->search_product_layout->value,
            'search_group_layout' => $this->search_group_layout->value,
            'search_items_per_page' => $this->search_items_per_page,
            'social_media' => $this->whenLoaded(
                'socialMedia',
                fn () => $this->socialMedia
                    ->map(fn ($socialMedia) => [
                        'code' => $socialMedia->code,
                        'icon' => $socialMedia->icon,
                        'name' => $socialMedia->name,
                        'url' => $socialMedia->pivot->url,
                    ])
                    ->values()
            ),
            'menues' => $this->whenLoaded(
                'menues',
                fn () => $this->menuTree($this->menues)
            ),
            'categories' => $this->whenLoaded(
                'categories',
                fn () => $this->categoryTree($this->categories)
            ),
        ];
    }

    private function formatExtraConfig(mixed $value): mixed
    {
        if ($value instanceof Attachment) {
            return $value->getTemporaryUrl(1440);
        }

        if (! is_array($value)) {
            return $value;
        }

        foreach ($value as $key => $item) {
            $value[$key] = $this->formatExtraConfig($item);
        }

        return $value;
    }

    /**
     * @param  Collection<int, Category>  $categories
     * @return Collection<int, array<string, mixed>>
     */
    private function categoryTree(Collection $categories): Collection
    {
        $categoryIds = $categories->pluck('id')->flip();
        $childrenByParent = $categories
            ->filter(fn (Category $category) => $category->categoria_id !== null
                && $categoryIds->has($category->categoria_id))
            ->groupBy('categoria_id');

        $formatCategory = function (Category $category) use (&$formatCategory, $childrenByParent): array {
            return [
                'id' => $category->id,
                'nombre' => $category->nombre,
                'subcategories' => $childrenByParent
                    ->get($category->id, collect())
                    ->map($formatCategory)
                    ->values(),
            ];
        };

        return $categories
            ->filter(fn (Category $category) => $category->categoria_id === null
                || ! $categoryIds->has($category->categoria_id))
            ->map($formatCategory)
            ->values();
    }

    /**
     * @param  Collection<int, Menu>  $menus
     * @return Collection<int, array<string, mixed>>
     */
    private function menuTree(Collection $menus): Collection
    {
        $menuCodes = $menus->pluck('code')->flip();
        $childrenByParent = $menus
            ->filter(fn (Menu $menu) => $menu->parent_menu_code !== null)
            ->groupBy('parent_menu_code');

        $formatMenu = function (Menu $menu) use (&$formatMenu, $childrenByParent): array {
            $formatted = [
                'id' => $menu->id,
                'code' => $menu->code,
                'label' => $menu->label,
                'parent_menu_code' => $menu->parent_menu_code,
                'content_type' => $menu->content_type,
                'route' => $menu->route,
            ];

            if ($menu->pivot?->static_content !== null) {
                $formatted['static_content'] = $menu->pivot->static_content;
            }

            $formatted['submenues'] = $childrenByParent
                ->get($menu->code, collect())
                ->map($formatMenu)
                ->values();

            return $formatted;
        };

        return $menus
            ->filter(fn (Menu $menu) => $menu->parent_menu_code === null
                || ! $menuCodes->has($menu->parent_menu_code))
            ->map($formatMenu)
            ->values();
    }
}
