<?php

namespace App\Services\Admin\Products;

use App\Http\Requests\Admin\ProductCategoryStoreRequest;
use App\Http\Requests\Admin\ProductCategoryUpdateRequest;
use App\Models\ProductCategory;
use App\Models\SpecificationKey;

class ProductCategoriesService
{
    /** get categories list */
    public function getCategories()
    {
        $categories = ProductCategory::where('status', 'publish')->where('parent_id', 0)->withCount('products')->get()->map(fn($catLevel1) => [
            'id' => $catLevel1->id,
            'title' => $catLevel1->title,
            'slug' => $catLevel1->slug,
            'get_formatted_view_count' => $catLevel1->get_formatted_view_count,
            'products_count' => $catLevel1->products_count,
            'childs' => $catLevel1->childs->map(fn($catLevel2) => [
                'id' => $catLevel2['id'],
                'title' => $catLevel2['title'],
                'slug' => $catLevel2['slug'],
                'get_formatted_view_count' => $catLevel2['get_formatted_view_count'],
                'products_count' => $catLevel2['products_count'],
                'childs' => $catLevel2['childs']->map(fn($catLevel3) => [
                    'id' => $catLevel3['id'],
                    'title' => $catLevel3['title'],
                    'slug' => $catLevel3['slug'],
                    'get_formatted_view_count' => $catLevel3['get_formatted_view_count'],
                    'products_count' => $catLevel3['products_count'],
                    'childs' => $catLevel3['childs'],
                ]),
            ]),
        ]);

        return $categories;
    }

    /** create specifications */
    public function createSpecifications(ProductCategory $category, ProductCategoryStoreRequest $request)
    {
        if ($category != null && $request->exists('specifications') && is_array($request->specifications)) {
            foreach ($request->specifications as $specification) {
                if ($specification['title'] == null) {
                    return redirect()->back()->withErrors(['messages.specification_title_required']);
                }

                $specificationGroup = $category->specifications()->create([
                    'title' => $specification['title']
                ]);

                if ($specificationGroup != null && is_array($specification['keys'])) {
                    foreach ($specification['keys'] as $specificationKey) {
                        if ($specificationKey['key'] == null) {
                            return redirect()->back()->withErrors(['messages.specification_key_required']);
                        }

                        $specificationGroup->specificationKeys()->create([
                            'key' => $specificationKey['key'],
                            'default_value' => $specificationKey['value'],
                        ]);
                    }
                }
            }
        }
    }

    /** init specifications */
    public function initSpecifications(ProductCategory $category, ProductCategoryUpdateRequest $request)
    {
        // delete specification
        $this->deleteSpecifications($category, $request);

        // add or update specifications
        $this->updateSpecifications($category, $request);
    }

    /** delete specifications */
    public function deleteSpecifications(ProductCategory $category, ProductCategoryUpdateRequest $request)
    {
        /** delete specification */
        $specificationsID = $category->specifications()->get()->map(fn($specification) => [
            'id' => $specification->id,
        ])->pluck('id')->toArray();
        $removedSpecifications = array_diff($specificationsID, array_column($request->specifications, 'id'));
        foreach ($removedSpecifications as $r) {
            $category->specifications()->where('id', $r)->first()->delete();
        }

        /** delete specification keys */
        $specificationKeys = $category->specifications()->get()->map(fn($specification) => [
            'keys' => $specification->specificationKeys()->get()->map(fn($specificationKey) => [
                'id' => $specificationKey->id,
                'key' => $specificationKey->key,
                'value' => $specificationKey->default_value,
            ])->toArray()
        ])->toArray();
        $existingKeys = [];
        foreach (array_column($specificationKeys, 'keys') as $keys) {
            $existingKeys = array_merge($existingKeys, array_column($keys, 'id'));
        }
        $requestKeys = [];
        foreach (array_column($request->specifications, 'keys') as $keys) {
            $requestKeys = array_merge($requestKeys, array_column($keys, 'id'));
        }
        $removedSpecificationKeys = array_diff($existingKeys, $requestKeys);
        foreach ($removedSpecificationKeys as $r) {
            SpecificationKey::where('id', $r)->first()->delete();
        }
    }

    /** update specifications */
    public function updateSpecifications(ProductCategory $category, ProductCategoryUpdateRequest $request)
    {
        /** update or create specifications ans keys */
        if ($category != null && is_array($request->specifications)) {
            foreach ($request->specifications as $specification) {
                if (array_key_exists('id', $specification)) {
                    // update exsiting specification
                    $specificationModel = $category->specifications()->where('id', $specification['id'])->first();
                    if ($specificationModel != null) {
                        $specificationModel->update([
                            'title' => $specification['title']
                        ]);

                        if (is_array($specification['keys'])) {
                            foreach ($specification['keys'] as $specificationKey) {
                                if (array_key_exists('id', $specificationKey)) {
                                    // update exsiting specification key
                                    $specificationKeyModel = $specificationModel->specificationKeys()->where('id', $specificationKey['id'])->first();
                                    if ($specificationKeyModel != null) {
                                        $specificationKeyModel->update([
                                            'key' => $specificationKey['key'],
                                            'default_value' => $specificationKey['value'],
                                        ]);
                                    }
                                } else {
                                    // create new specification key
                                    $specificationModel->specificationKeys()->create([
                                        'key' => $specificationKey['key'],
                                        'default_value' => $specificationKey['value'],
                                    ]);
                                }
                            }
                        }
                    }
                } else {
                    // create new specification
                    $specificationGroup = $category->specifications()->create([
                        'title' => $specification['title']
                    ]);

                    if ($specificationGroup != null && is_array($specification['keys'])) {
                        foreach ($specification['keys'] as $specificationKey) {
                            // create new specification key
                            $specificationGroup->specificationKeys()->create([
                                'key' => $specificationKey['key'],
                                'default_value' => $specificationKey['value'],
                            ]);
                        }
                    }
                }
            }
        }
    }
}
