<?php
namespace EasyChat\Controller;

use EasyChat\Library\Crm\Bitrix24Webhook;
use EasyChat\Library\Crm\CrmProviderRegistry;
use EasyChat\Model\CrmConnection;

final class CrmIntegration extends Base {
    protected $layouts = 'layout';

    public function __construct($registry) {
        parent::__construct($registry);
        $session = \EasyChat\Library\RequestContext::session();
        if (empty($session['manager_id']) || ($session['manager_role'] ?? '') !== 'admin') {
            header('Location: index.php?route=auth'); exit;
        }
    }

    public function index() {
        $model = new CrmConnection($this->registry);
        $connection = $model->getPrimary('bitrix24', false);
        $amo = $model->getPrimary('amocrm', false);
        $retail = $model->getPrimary('retailcrm', false);
        $this->vars['title'] = 'CRM | EasyChat';
        $this->vars['crm_connection'] = $connection;
        $this->vars['amo_connection'] = $amo;
        $this->vars['retailcrm_connection'] = $retail;
        $this->vars['crm_webhook_mask'] = $connection ? 'Сохранен защищенно' : '';
        $this->vars['amo_token_mask'] = $amo ? 'Сохранен защищенно' : '';
        $this->vars['retailcrm_key_mask'] = $retail ? 'Сохранен защищенно' : '';
        $this->vars['crm_nonce'] = $this->nonce();
        $this->template->view('crm_integration');
    }

    public function save() {
        $this->requirePost();
        if (!$this->validNonce()) $this->json(403, array('success'=>false,'error'=>'Сессия устарела. Обновите страницу.','nonce'=>$this->nonce()));
        try {
            $post = \EasyChat\Library\RequestContext::post();
            $provider = (string)($post['provider'] ?? 'bitrix24');
            $model = new CrmConnection($this->registry);
            if ($provider === 'retailcrm') {
                $connection = $model->saveRetailCrm(array(
                    'base_domain'=>(string)($post['base_domain'] ?? ''),'api_key'=>(string)($post['api_key'] ?? ''),
                    'entity_mode'=>(string)($post['entity_mode'] ?? 'customer'),'site'=>(string)($post['site'] ?? ''),
                    'responsible_id'=>(int)($post['responsible_id'] ?? 0),'order_method'=>(string)($post['order_method'] ?? ''),
                    'order_type'=>(string)($post['order_type'] ?? ''),'order_status'=>(string)($post['order_status'] ?? ''),
                    'enabled'=>!empty($post['enabled']),
                ));
            } elseif ($provider === 'amocrm') {
                $connection = $model->saveAmoCrm(array(
                    'base_domain'=>(string)($post['base_domain'] ?? ''),'access_token'=>(string)($post['access_token'] ?? ''),
                    'pipeline_id'=>(int)($post['pipeline_id'] ?? 0),'status_id'=>(int)($post['status_id'] ?? 0),
                    'responsible_id'=>(int)($post['responsible_id'] ?? 0),'enabled'=>!empty($post['enabled']),
                    'trigger_digital_pipeline'=>!empty($post['trigger_digital_pipeline']),
                ));
            } else {
                $provider = 'bitrix24';
                $connection = $model->saveBitrix24(array(
                    'webhook_url' => (string)($post['webhook_url'] ?? ''),
                    'entity_mode' => (string)($post['entity_mode'] ?? 'lead'),
                    'responsible_id' => (int)($post['responsible_id'] ?? 0),
                    'enabled' => !empty($post['enabled']),
                ));
            }
            $this->json(200, array('success'=>true,'message'=>'Настройки сохранены.','provider'=>$provider,'connection'=>$this->publicConnection($connection),'nonce'=>$this->nonce()));
        } catch (\InvalidArgumentException $e) {
            $messages = array(
                'retailcrm_site_required'=>'Укажите символьный код магазина RetailCRM.',
                'retailcrm_credentials_invalid'=>'Проверьте домен аккаунта и API-ключ RetailCRM.',
                'amocrm_configuration_incomplete'=>'Сначала выберите воронку, стадию и подготовьте поля amoCRM.',
                'amocrm_credentials_invalid'=>'Проверьте домен аккаунта и долгосрочный токен amoCRM.',
            );
            $message = $messages[$e->getMessage()] ?? 'Проверьте адрес входящего вебхука Битрикс24.';
            $this->json(422, array('success'=>false,'error'=>$message,'nonce'=>$this->nonce()));
        } catch (\Throwable $e) {
            $this->json(500, array('success'=>false,'error'=>'Не удалось сохранить подключение.','nonce'=>$this->nonce()));
        }
    }

    public function test() {
        $this->requirePost();
        if (!$this->validNonce()) $this->json(403, array('success'=>false,'error'=>'Сессия устарела. Обновите страницу.','nonce'=>$this->nonce()));
        $post = \EasyChat\Library\RequestContext::post();
        $provider = (string)($post['provider'] ?? 'bitrix24');
        if (!in_array($provider, array('bitrix24','amocrm','retailcrm'), true)) $provider = 'bitrix24';
        $model = new CrmConnection($this->registry);
        $connection = $model->getPrimary($provider, true);
        if (!$connection) $this->json(422, array('success'=>false,'error'=>'Сначала сохраните подключение.','nonce'=>$this->nonce()));
        $result = (new CrmProviderRegistry($this->registry))->get($provider)->testConnection($connection);
        $model->recordHealth((int)$connection['connection_id'], !empty($result['success']), (string)($result['error'] ?? ''));
        if (empty($result['success'])) $this->json(502, array('success'=>false,'error'=>$this->friendlyError((string)($result['error'] ?? '')),'nonce'=>$this->nonce()));
        $message = $provider === 'amocrm' ? 'amoCRM отвечает. Выберите воронку и стадию.' : ($provider === 'retailcrm' ? 'RetailCRM отвечает. Проверьте магазин и сохраните подключение.' : 'Битрикс24 отвечает. Подключение готово.');
        $payload = array('success'=>true,'message'=>$message,'portal'=>(string)($result['portal'] ?? ''),'nonce'=>$this->nonce());
        if ($provider === 'amocrm') $payload['pipelines'] = (array)($result['pipelines'] ?? array());
        if ($provider === 'retailcrm') $payload['sites'] = (array)($result['sites'] ?? array());
        $this->json(200, $payload);
    }

    public function prepare() {
        $this->requirePost();
        if (!$this->validNonce()) $this->json(403, array('success'=>false,'error'=>'Сессия устарела. Обновите страницу.','nonce'=>$this->nonce()));
        $model = new CrmConnection($this->registry);
        $connection = $model->getPrimary('amocrm', true);
        if (!$connection) $this->json(422, array('success'=>false,'error'=>'Сначала сохраните домен и токен amoCRM.','nonce'=>$this->nonce()));
        $result = (new CrmProviderRegistry($this->registry))->get('amocrm')->prepareFields($connection);
        if (empty($result['success'])) $this->json(502, array('success'=>false,'error'=>$this->friendlyError((string)($result['error'] ?? '')),'nonce'=>$this->nonce()));
        $saved = $model->updateAmoFieldMapping((array)$result['field_mapping']);
        $this->json(200, array('success'=>true,'message'=>'Поля EasyChat готовы в amoCRM.','connection'=>$this->publicConnection($saved),'nonce'=>$this->nonce()));
    }

    private function publicConnection(array $connection): array {
        return array(
            'status'=>(string)($connection['status'] ?? 'disabled'),'entity_mode'=>(string)($connection['entity_mode'] ?? 'lead'),
            'responsible_id'=>(int)($connection['responsible_id'] ?? 0),'pipeline_id'=>(int)($connection['pipeline_id'] ?? 0),
            'status_id'=>(int)($connection['status_id'] ?? 0),'fields_ready'=>!empty($connection['field_mapping']['origin_field_id']) && !empty($connection['field_mapping']['dialog_field_id']) && !empty($connection['field_mapping']['source_field_id']),
            'site'=>(string)($connection['site'] ?? ''),
        );
    }
    private function friendlyError(string $error): string {
        if (in_array($error, array('NO_AUTH_FOUND','INVALID_CREDENTIALS','crm_credentials_invalid'), true)) return 'Битрикс24 отклонил доступ. Проверьте вебхук и права CRM.';
        if ($error === 'crm_remote_host_denied') return 'Адрес портала не прошел безопасную сетевую проверку.';
        if (strpos($error, 'LIMIT') !== false) return 'Битрикс24 временно ограничил запросы. Повторите проверку позже.';
        if (strpos($error, 'amocrm_http_401') !== false) return 'amoCRM отклонила токен. Создайте новый долгосрочный токен и сохраните его.';
        if (strpos($error, 'amocrm_http_403') !== false) return 'У токена amoCRM недостаточно прав для этого действия.';
        if (strpos($error, 'amocrm_http_402') !== false) return 'amoCRM заблокировала запись по условиям текущего тарифа аккаунта.';
        if (strpos($error, 'amocrm_') === 0) return 'amoCRM не выполнила запрос. Проверьте токен, права и настройки воронки.';
        if (strpos($error, 'retailcrm_http_401') === 0 || strpos($error, 'retailcrm_http_403') === 0) return 'RetailCRM отклонила API-ключ или его права.';
        if ($error === 'retailcrm_site_required') return 'RetailCRM требует символьный код доступного магазина.';
        if (strpos($error, 'retailcrm_') === 0) return 'RetailCRM не выполнила запрос. Проверьте API-ключ, магазин и права доступа.';
        return 'Битрикс24 сейчас не ответил. Проверьте адрес, доступность портала и попробуйте еще раз.';
    }
    private function requirePost(): void {
        if (\EasyChat\Library\RequestContext::method() !== 'POST') $this->json(405, array('success'=>false,'error'=>'Метод не поддерживается.'));
    }
    private function validNonce(): bool {
        $expected = (string)(\EasyChat\Library\RequestContext::session()['easychat_crm_nonce'] ?? '');
        $actual = (string)(\EasyChat\Library\RequestContext::post()['nonce'] ?? '');
        return $expected !== '' && $actual !== '' && hash_equals($expected, $actual);
    }
    private function nonce(): string {
        $session =& \EasyChat\Library\RequestContext::session();
        if (empty($session['easychat_crm_nonce'])) $session['easychat_crm_nonce'] = bin2hex(random_bytes(16));
        return (string)$session['easychat_crm_nonce'];
    }
    private function json(int $status, array $payload): void {
        http_response_code($status); header('Content-Type: application/json; charset=utf-8'); header('Cache-Control: no-store');
        echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit;
    }
}
