<?php

namespace KupShop\ComponentsBundle\Twig\Components\Account;

use KupShop\BonusProgramBundle\Utils\BonusComputer;
use KupShop\BonusProgramBundle\Utils\BonusProvider;
use KupShop\ComponentsBundle\Attributes\Component;
use KupShop\ComponentsBundle\Attributes\Version;
use KupShop\ComponentsBundle\Twig\BaseComponent;
use KupShop\KupShopBundle\Context\UserContext;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\PreordersBundle\Service\PreorderUtil;
use KupShop\UserManagerBundle\Util\UserManagerUtil;
use Query\Operator;
use Query\QueryBuilder;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
use Symfony\UX\TwigComponent\Attribute\PostMount;

#[AsTwigComponent(template: '@Components/components/Account/Menu/Menu.1.html.twig')]
#[Component(1, [
    new Version(1, newJs: null),
])]
class Menu extends BaseComponent
{
    use UserInfoTrait;

    public ?\User $user;
    protected array $menu;

    public function __construct(
        protected RequestStack $requestStack,
        protected ?UserManagerUtil $userManagerUtil,
        protected ?BonusComputer $bonusComputer,
        protected ?BonusProvider $bonusProvider,
        private readonly TranslatorInterface $translator,
    ) {
    }

    #[PostMount]
    public function setUser()
    {
        if (!isset($this->user)) {
            $this->user = Contexts::get(UserContext::class)->getActive();
        }
    }

    public function getUserName(): string
    {
        $name = [trim($this->user->name), trim($this->user->surname)];
        $name = array_filter($name);

        return join(' ', $name);
    }

    public function getMenu(): array
    {
        if (!isset($this->user)) {
            return ['login' => [
                'url' => path('kupshop_user_login_login'),
                'title' => $this->translator->trans('login.modal.title', [], 'users'),
                'active' => true,
            ]];
        }

        if (!isset($this->menu)) {
            $this->menu = [];

            $dbcfg = \Settings::getDefault();
            $request = $this->requestStack->getMainRequest();
            $currentRoute = $request->attributes->get('_route');

            $this->menu['account'] = [
                'url' => path('account'),
                'title' => $this->translator->trans('my.account', [], 'users'),
                'active' => ($currentRoute == 'account'),
            ];

            $this->menu['user_edit'] = [
                'url' => path('settings'),
                'title' => $this->translator->trans('personal.details', [], 'users'),
                'active' => ($currentRoute == 'settings'),
            ];

            if (findModule(\Modules::ORDERS)) {
                $orders_count = (int) sqlQueryBuilder()->select('COUNT(*)')->from('orders')
                    ->andWhere(Operator::equals(['id_user' => $this->user->id]))
                    ->execute()->fetchOne();
                $this->menu['orders'] = [
                    'url' => path('orders'),
                    'title' => $this->translator->trans('info.orders', [], 'users'),
                    'count' => $orders_count,
                    'active' => ($currentRoute == 'orders' || $currentRoute == 'kupshop_content_orders_order'),
                ];
            }

            if (findModule(\Modules::USER_MANAGER)) {
                if ($this->userManagerUtil->isUserManager($this->user->id)) {
                    $this->menu['user_manager'] = [
                        'url' => path('kupshop_usermanager_usermanager_userslist'),
                        'title' => $this->translator->trans('branch.management', [], 'users'),
                        'active' => ($currentRoute == 'kupshop_usermanager_usermanager_userslist'),
                    ];
                }
            }

            if (findModule(\Modules::AGE_VERIFY)) {
                $this->menu['age_verify'] = [
                    'url' => path('ageVerify'),
                    'title' => $this->translator->trans('age.verify', [], 'users'),
                    'active' => ($currentRoute == 'ageVerify'),
                ];
            }

            if (findModule(\Modules::SALES)) {
                $count = (int) sqlQueryBuilder()->select('COUNT(*)')->from('sales')
                    ->where(Operator::equals(['id_user' => $this->user->id]))
                    ->execute()->fetchOne();
                $this->menu['sales'] = [
                    'url' => path('kupshop_sales_sales_list'),
                    'title' => $this->translator->trans('my.purchases.shop', [], 'users'),
                    'count' => $count,
                    'active' => ($currentRoute == 'kupshop_sales_sales_list'),
                ];
            }

            if ($this->canUserCreatePreorder($this->user)) {
                $count = PreorderUtil::countUserPreorders($this->user);
                $this->menu['preorders'] = [
                    'url' => path('kupshop_preorders_show_user'),
                    'title' => $this->translator->trans('preorders', [], 'users'),
                    'count' => $count,
                    'active' => ($currentRoute == 'kupshop_preorders_show_user'),
                ];
            }

            if (findModule(\Modules::BONUS_PROGRAM)) {
                if ($this->bonusComputer->isBonusProgramActive()) {
                    $count = $this->bonusProvider->getActivePointsAmount($this->user);
                    $this->menu['bonus_program'] = [
                        'url' => path('kupshop_bonusprogram_bonusprogramhistory_account'),
                        'title' => $this->translator->trans('bonus.programme', [], 'users'),
                        'count' => "{$count} b.",
                        'active' => ($currentRoute == 'kupshop_bonusprogram_bonusprogramhistory_account'),
                    ];
                }
                if (findModule(\Modules::BONUS_PROGRAM, \Modules::SUB_POINTS_EXCHANGE)) {
                    $this->menu['bonus_program_exchange'] = [
                        'url' => path('kupshop_bonusprogram_bonusprogramexchange_exchangelist'),
                        'title' => $this->translator->trans('change.bonus.points', [], 'users'),
                        'active' => ($currentRoute == 'kupshop_bonusprogram_bonusprogramexchange_exchangelist'),
                    ];
                    $this->menu['bonus_program_coupons'] = [
                        'url' => path('kupshop_bonusprogram_bonusprogramexchange_couponlist'),
                        'title' => $this->translator->trans('my.vouchers', [], 'users'),
                        'active' => ($currentRoute == 'kupshop_bonusprogram_bonusprogramexchange_couponlist'),
                    ];
                }
            }

            if (findModule(\Modules::PRODUCTS_FAVORITES)) {
                $productList = new \ProductList();
                $productList->applyDefaultFilterParams();
                $productList->andSpec(function (QueryBuilder $qb) {
                    $qb->join('p', 'products_favorites', 'pf', 'pf.id_product = p.id');
                    $qb->andWhere(Operator::equals(['pf.id_user' => $this->user->id]));
                });
                if ($count = $productList->getProductsCount()) {
                    $this->menu['favorites'] = [
                        'url' => path('kupshop_catalog_catalog_favourite'),
                        'title' => $this->translator->trans('favourite.products', [], 'users'),
                        'count' => $count,
                        'active' => ($currentRoute == 'kupshop_catalog_catalog_favourite'),
                    ];
                }
            }

            if (findModule(\Modules::WATCHDOG)) {
                $count = sqlQueryBuilder()
                    ->select('COUNT(*)')
                    ->from('products_watchdog')
                    ->where(Operator::equals(['id_user' => $this->user->id]))
                    ->execute()
                    ->fetchOne();

                if ($count) {
                    $this->menu['watchdog'] = [
                        'url' => path('kupshop_watchdog_watchdog_watchdog'),
                        'title' => $this->translator->trans('watched.products', [], 'users'),
                        'count' => $count,
                        'active' => ($currentRoute == 'kupshop_watchdog_watchdog_watchdog'),
                    ];
                }
            }

            if (findModule(\Modules::SHOPPING_LIST)) {
                $count = sqlQueryBuilder()->select('COUNT(*)')->from('shopping_list')
                    ->where(Operator::equals(['id_user' => $this->user->id]))
                    ->execute()->fetchOne();
                $this->menu['shopping_list'] = [
                    'url' => path('kupshop_shoppinglist_shoppinglist_shoppinglist'),
                    'title' => $this->translator->trans('my.lists', [], 'users'),
                    'count' => $count,
                    'active' => ($currentRoute == 'kupshop_shoppinglist_shoppinglist_shoppinglist'),
                ];
            }

            if (findModule(\Modules::RECLAMATIONS) && !empty($orders_count)) {
                $adminOnly = (($dbcfg->reclamations['adminOnly'] ?? 'N') == 'Y');
                if (!$adminOnly || getAdminUser()) {
                    $count = sqlQueryBuilder()->select('COUNT(*)')->from('reclamations', 'r')
                        ->join('r', 'order_items', 'oi', 'oi.id=r.id_item')
                        ->join('oi', 'orders', 'o', 'oi.id_order=o.id')
                        ->where(Operator::equals(['o.id_user' => $this->user->id]))
                        ->execute()->fetchOne();
                    $this->menu['reclamations'] = [
                        'url' => path('kupshop_reclamations_reclamations_reclamations'),
                        'title' => $this->translator->trans('reclamations', [], 'users'),
                        'count' => $count,
                        'active' => ($currentRoute == 'kupshop_reclamations_reclamations_reclamations'),
                    ];
                }
            }

            if (findModule(\Modules::RETURNS) && !empty($orders_count)) {
                $adminOnly = (($dbcfg->returns['adminOnly'] ?? 'N') == 'Y');
                if (!$adminOnly || getAdminUser()) {
                    $allowCreateReturns = true;
                    if (findModule(\Modules::B2B)
                        && (($dbcfg->b2b['allowCreateReturns'] ?? 'N') != 'Y')
                        && $this->user->isType('b2b')) {
                        // B2B are not allowed to create returns.
                        $allowCreateReturns = false;
                    }
                    if ($allowCreateReturns) {
                        $count = sqlQueryBuilder()->select('COUNT(*)')->from('returns', 'r')
                            ->join('r', 'return_items', 'ri', 'r.id = ri.id_return')
                            ->join('ri', 'order_items', 'oi', 'oi.id = ri.id_item')
                            ->join('oi', 'orders', 'o', 'oi.id_order=o.id')
                            ->where(Operator::equals(['o.id_user' => $this->user->id]))
                            ->execute()->fetchOne();
                        $this->menu['returns'] = [
                            'url' => path('kupshop_returns_returns_returns'),
                            'title' => $this->translator->trans('return.products', [], 'users'),
                            'count' => $count,
                            'active' => ($currentRoute == 'kupshop_returns_returns_returns'),
                        ];
                    }
                }
            }

            $this->menu['logout'] = [
                'url' => path('kupshop_user_login_logout'),
                'title' => $this->translator->trans('log.out', [], 'users'),
            ];
        }

        return $this->menu;
    }

    private function canUserCreatePreorder(\User $user): bool
    {
        if (!findModule(\Modules::B2B_PREORDERS)) {
            return false;
        }

        $allowedUserGroupsInOpenPreorders = sqlQueryBuilder()
            ->select("JSON_EXTRACT(po.settings, '$.users_groups') AS groups")
            ->from('preorders', 'po')
            ->andWhere("JSON_EXTRACT(po.settings, '$.users_groups') IS NOT NULL")
            ->andWhere(Operator::exists(
                sqlQueryBuilder()->select('*')
                    ->from('preorders_dates', 'pd')
                    ->andWhere(PreorderUtil::specDateIsOpen())
                    ->andWhere('pd.id_preorder = po.id'),
            ));

        $allowedGroups = array_merge(
            ...array_map(fn (string $groups) => json_decode($groups, true),
                $allowedUserGroupsInOpenPreorders->execute()->fetchFirstColumn(),
            ));

        return !empty(array_intersect_key(
            $user->getGroups(),
            array_fill_keys($allowedGroups, true),
        ));
    }
}
