<?php

declare(strict_types=1);

namespace App\Handlers;

use App\Services\SettingsService;
use App\Support\Utils;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\ImageTool\ImageToolInterface;
use Openguru\OpenCartFramework\QueryBuilder\Builder;
use Openguru\OpenCartFramework\QueryBuilder\JoinClause;

class CategoriesHandler
{
    private const THUMB_SIZE = 150;

    private Builder $queryBuilder;
    private ImageToolInterface $ocImageTool;
    private SettingsService $settings;

    public function __construct(Builder $queryBuilder, ImageToolInterface $ocImageTool, SettingsService $settings)
    {
        $this->queryBuilder = $queryBuilder;
        $this->ocImageTool = $ocImageTool;
        $this->settings = $settings;
    }

    public function index(Request $request): JsonResponse
    {
        $languageId = $this->settings->config()->getApp()->getLanguageId();

        $perPage = $request->get('perPage', 100);

        $categoriesFlat = $this->queryBuilder->newQuery()
            ->select([
                'categories.category_id' => 'id',
                'categories.parent_id' => 'parent_id',
                'categories.image' => 'image',
                'descriptions.name' => 'name',
                'descriptions.description' => 'description',
            ])
            ->from(db_table('category'), 'categories')
            ->join(
                db_table('category_description') . ' AS descriptions',
                function (JoinClause $join) use ($languageId) {
                    $join->on('categories.category_id', '=', 'descriptions.category_id')
                        ->where('descriptions.language_id', '=', $languageId);
                }
            )
            ->where('categories.status', '=', 1)
            ->orderBy('parent_id')
            ->orderBy('sort_order')
            ->get();

        $categories = $this->buildCategoryTree($categoriesFlat);

        $categories = array_slice($categories, 0, $perPage);

        return new JsonResponse([
            'data' => array_map(static function ($category) {
                return [
                    'id' => (int) $category['id'],
                    'image' => $category['image'] ?? '',
                    'name' => Utils::htmlEntityEncode($category['name']),
                    'description' => $category['description'],
                    'children' => $category['children'],
                ];
            }, $categories),
        ]);
    }

    public function buildCategoryTree(array $flat, $parentId = 0): array
    {
        $branch = [];

        foreach ($flat as $category) {
            if ((int) $category['parent_id'] === (int) $parentId) {
                $children = $this->buildCategoryTree($flat, $category['id']);
                if ($children) {
                    $category['children'] = $children;
                }

                $image = $this->ocImageTool->resize(
                    $category['image'] ?? '',
                    self::THUMB_SIZE,
                    self::THUMB_SIZE,
                    'no_image.png'
                );

                $branch[] = [
                    'id' => (int) $category['id'],
                    'image' => $image,
                    'name' => Utils::htmlEntityEncode($category['name']),
                    'description' => $category['description'],
                    'children' => $category['children'] ?? [],
                ];
            }
        }

        return $branch;
    }
}
