<?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)
            ->orderBy('sort_id')
            ->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,
            ]);

        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'],
                            ]);
                        }
                    }
                }
            }
        }
    }
}
