<?php
namespace EasyChat\Controller;

use EasyChat\Library\Delivery\CdekTrackingProvider;
use EasyChat\Library\Delivery\DeliveryConnection;
use EasyChat\Library\Delivery\RussianPostTrackingProvider;
use EasyChat\Library\Delivery\YandexDeliveryTrackingProvider;
use EasyChat\Library\Delivery\ApiShipTrackingProvider;
use EasyChat\Library\RequestContext;

final class DeliveryIntegration extends Base
{
    public function __construct($registry)
    {
        parent::__construct($registry);
        $session = RequestContext::session();
        if (empty($session['manager_id']) || ($session['manager_role'] ?? '') !== 'admin') {
            $this->json(403, array('success' => false, 'error' => 'Недостаточно прав.'));
        }
    }

    





    public function index(): void
    {
        $this->json(404, array('success' => false, 'error' => 'Маршрут не найден.'));
    }

    public function save(): void
    {
        $this->postAndNonce();
        $post = RequestContext::post();
        try {
            $state = (new DeliveryConnection($this->registry))->save(array(
                'russian_post' => array(
                    'enabled' => !empty($post['russian_post_enabled']),
                    'login' => (string)($post['russian_post_login'] ?? ''),
                    'password' => (string)($post['russian_post_password'] ?? ''),
                ),
                'cdek' => array(
                    'enabled' => !empty($post['cdek_enabled']),
                    'client_id' => (string)($post['cdek_client_id'] ?? ''),
                    'client_secret' => (string)($post['cdek_client_secret'] ?? ''),
                ),
                'yandex_delivery' => array(
                    'enabled' => !empty($post['yandex_delivery_enabled']),
                    'token' => (string)($post['yandex_delivery_token'] ?? ''),
                ),
                'apiship' => array(
                    'enabled' => !empty($post['apiship_enabled']),
                    'token' => (string)($post['apiship_token'] ?? ''),
                ),
                'opencart_shipping_mapping' => (string)($post['opencart_shipping_mapping'] ?? ''),
            ));
            $this->json(200, array('success' => true, 'message' => 'Настройки доставки сохранены.', 'state' => $state, 'nonce' => $this->nonce()));
        } catch (\InvalidArgumentException $e) {
            $message = $e->getMessage() === 'opencart_shipping_mapping_invalid'
                ? 'Не удалось прочитать выбранные способы доставки OpenCart. Обновите страницу и повторите.'
                : 'Для включённого сервиса заполните необходимые доступы.';
            $this->json(422, array('success' => false, 'error' => $message, 'nonce' => $this->nonce()));
        } catch (\RuntimeException $e) {
             
             
            if ($e->getMessage() === 'install_secret_required') {
                $this->json(422, array('success' => false, 'error' => 'Не найден секрет установки. Обновите конфигурацию EasyChat или обратитесь к администратору сервера.', 'nonce' => $this->nonce()));
            }
            error_log('EasyChat delivery save runtime error: ' . $e->getMessage());
            $this->json(500, array('success' => false, 'error' => 'Не удалось сохранить настройки доставки. Проверьте журнал EasyChat.', 'nonce' => $this->nonce()));
        } catch (\Throwable $e) {
             
            error_log('EasyChat delivery save error: ' . get_class($e) . ': ' . $e->getMessage());
            $this->json(500, array('success' => false, 'error' => 'Не удалось сохранить настройки доставки. Проверьте журнал EasyChat.', 'nonce' => $this->nonce()));
        }
    }

    public function test(): void
    {
        $this->postAndNonce();
        $post = RequestContext::post();
        $provider = strtolower(trim((string)($post['test_provider'] ?? '')));
        $tracking = trim((string)($post['tracking_number'] ?? ''));
        if (!in_array($provider, array('cdek', 'russian_post', 'yandex_delivery', 'apiship'), true)) {
            $this->json(422, array('success' => false, 'error' => 'Выберите сервис доставки для проверки.', 'nonce' => $this->nonce()));
        }
        if (!$this->validIdentifier($provider, $tracking)) {
            $this->json(422, array('success' => false, 'error' => $this->identifierError($provider), 'nonce' => $this->nonce()));
        }
        try {
            $connection = new DeliveryConnection($this->registry);
            $credentials = $connection->credentials($provider);
            if (empty($credentials['enabled'])) {
                $this->json(422, array('success' => false, 'error' => 'Сначала сохраните и включите выбранный сервис.', 'nonce' => $this->nonce()));
            }
            if ($provider === 'cdek') {
                $adapter = new CdekTrackingProvider($this->registry, (string)($credentials['client_id'] ?? ''), (string)($credentials['client_secret'] ?? ''));
            } elseif ($provider === 'yandex_delivery') {
                $adapter = new YandexDeliveryTrackingProvider($this->registry, (string)($credentials['token'] ?? ''));
            } elseif ($provider === 'apiship') {
                $adapter = new ApiShipTrackingProvider($this->registry, (string)($credentials['token'] ?? ''));
            } else {
                $adapter = new RussianPostTrackingProvider($this->registry, (string)($credentials['login'] ?? ''), (string)($credentials['password'] ?? ''));
            }
            $result = $adapter->track($tracking);
            $status = (string)($result['status'] ?? 'unavailable');
            if ($status !== 'ready') {
                $message = $status === 'not_found'
                    ? 'Отправление не найдено среди доступных этой учётной записи.'
                    : 'Сервис не подтвердил подключение. Проверьте доступы и повторите.';
                $this->json(502, array('success' => false, 'error' => $message, 'nonce' => $this->nonce()));
            }
            $shipment = (array)($result['shipment'] ?? array());
            $this->json(200, array(
                'success' => true,
                'message' => 'Подключение работает: ' . (string)($shipment['status_label'] ?? 'статус получен') . '.',
                'nonce' => $this->nonce(),
            ));
        } catch (\Throwable $e) {
            $this->json(502, array('success' => false, 'error' => 'Сервис доставки сейчас не ответил. Повторите проверку позже.', 'nonce' => $this->nonce()));
        }
    }

    private function postAndNonce(): void
    {
        if (RequestContext::method() !== 'POST') $this->json(405, array('success' => false, 'error' => 'Метод не поддерживается.'));
        $expected = (string)(RequestContext::session()['easychat_delivery_nonce'] ?? '');
        $actual = (string)(RequestContext::post()['nonce'] ?? '');
        if ($expected === '' || $actual === '' || !hash_equals($expected, $actual)) {
            $this->json(403, array('success' => false, 'error' => 'Сессия устарела. Обновите страницу.', 'nonce' => $this->nonce()));
        }
    }

    private function validIdentifier(string $provider, string $identifier): bool
    {
        if ($provider === 'yandex_delivery') return (bool)preg_match('/^[A-Za-z0-9-]{32,64}$/', $identifier);
        if ($provider === 'apiship') return (bool)preg_match('/^[A-Za-z0-9_.:-]{1,80}$/', $identifier);
        return (bool)preg_match('/^[A-Za-z0-9-]{5,40}$/', $identifier);
    }

    private function identifierError(string $provider): string
    {
        if ($provider === 'yandex_delivery') return 'Введите claim_id заявки Яндекс Доставки: 32–64 символа.';
        if ($provider === 'apiship') return 'Введите clientNumber заказа ApiShip.';
        return 'Введите корректный трек-номер.';
    }

    private function nonce(): string
    {
        $session =& RequestContext::session();
        if (empty($session['easychat_delivery_nonce'])) $session['easychat_delivery_nonce'] = bin2hex(random_bytes(16));
        return (string)$session['easychat_delivery_nonce'];
    }

    private function json(int $status, array $data): void
    {
        http_response_code($status);
        header('Content-Type: application/json; charset=utf-8');
        header('Cache-Control: no-store');
        echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        exit;
    }
}
