<?php

namespace Bastion\Handlers;

use Bastion\Exceptions\BotTokenConfiguratorException;
use Bastion\Services\BotTokenConfigurator;
use Bastion\Services\SettingsService;
use Exception;
use Openguru\OpenCartFramework\Cache\CacheInterface;
use Openguru\OpenCartFramework\Config\Settings;
use Openguru\OpenCartFramework\Http\JsonResponse;
use Openguru\OpenCartFramework\Http\Request;
use Openguru\OpenCartFramework\Http\Response;
use Openguru\OpenCartFramework\QueryBuilder\Builder;
use Openguru\OpenCartFramework\QueryBuilder\Connections\ConnectionInterface;
use Openguru\OpenCartFramework\Support\Arr;
use Psr\Log\LoggerInterface;

class SettingsHandler
{
    private BotTokenConfigurator $botTokenConfigurator;
    private Settings $settings;
    private SettingsService $settingsUpdateService;
    private CacheInterface $cache;
    private LoggerInterface $logger;
    private Builder $builder;
    private ConnectionInterface $connection;

    public function __construct(
        BotTokenConfigurator $botTokenConfigurator,
        Settings $settings,
        SettingsService $settingsUpdateService,
        CacheInterface $cache,
        LoggerInterface $logger,
        Builder $builder,
        ConnectionInterface $connection
    ) {
        $this->botTokenConfigurator = $botTokenConfigurator;
        $this->settings = $settings;
        $this->settingsUpdateService = $settingsUpdateService;
        $this->cache = $cache;
        $this->logger = $logger;
        $this->builder = $builder;
        $this->connection = $connection;
    }

    public function configureBotToken(Request $request): JsonResponse
    {
        try {
            $data = $this->botTokenConfigurator->configure(trim($request->json('botToken', '')));

            return new JsonResponse($data);
        } catch (BotTokenConfiguratorException $e) {
            return new JsonResponse(['error' => $e->getMessage()], Response::HTTP_UNPROCESSABLE_ENTITY);
        } catch (Exception $e) {
            return new JsonResponse(['error' => $e->getMessage()], Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function getSettingsForm(): JsonResponse
    {
        $data = Arr::getWithKeys($this->settings->getAll(), [
            'app',
            'telegram',
            'metrics',
            'store',
            'orders',
            'texts',
            'sliders',
            'mainpage_blocks',
        ]);

        $data['forms'] = [];

        $forms = $this->builder->newQuery()
            ->from('telecart_forms')
            ->get();

        if ($forms) {
            foreach ($forms as $form) {
                $schema = json_decode($form['schema'], true, 512, JSON_THROW_ON_ERROR);
                $data['forms'][$form['alias']] = [
                    'alias' => $form['alias'],
                    'friendly_name' => $form['friendly_name'],
                    'is_custom' => filter_var($form['is_custom'], FILTER_VALIDATE_BOOLEAN),
                    'schema' => $schema,
                ];
            }
        }

        return new JsonResponse(compact('data'));
    }

    public function saveSettingsForm(Request $request): JsonResponse
    {
        $input = $request->json();

        $this->validate($input);

        $this->settingsUpdateService->update(
            Arr::getWithKeys($input, [
                'app',
                'telegram',
                'metrics',
                'store',
                'orders',
                'texts',
                'sliders',
                'mainpage_blocks',
            ]),
        );

        // Update forms
        $forms = Arr::get($input, 'forms', []);
        foreach ($forms as $form) {
            $schema = json_encode($form['schema'], JSON_THROW_ON_ERROR);
            $this->builder->newQuery()
                ->where('alias', '=', $form['alias'])
                ->update('telecart_forms', [
                    'friendly_name' => $form['friendly_name'],
                    'is_custom' => $form['is_custom'],
                    'schema' => $schema,
                ]);
        }

        return new JsonResponse([], Response::HTTP_ACCEPTED);
    }

    private function validate(array $input): void
    {
    }

    public function resetCache(): JsonResponse
    {
        $this->cache->clear();

        $this->logger->info('Cache cleared manually.');

        return new JsonResponse([], Response::HTTP_ACCEPTED);
    }
}
