<?php
namespace EasyChat\Library\Messenger;

use EasyChat\Model\Messenger as MessengerModel;
use EasyChat\Model\Session;

 
class SmsConversationResolver {
    private $registry;
    private $db;
    private $prefix;

    public function __construct($registry) {
        $this->registry = $registry;
        $this->db = $registry->get('db');
        $this->prefix = easychat_db_prefix();
    }

    public function resolve(int $customer_id, string $phone, string $display_name): array {
        $phone = SmsPhoneNumber::normalize($phone);
        if ($customer_id <= 0 || $phone === '') {
            return ['success' => false, 'error' => 'confirmed_phone_required'];
        }
        $channel = (new SmsOutboundService($this->registry))->ensureChannel();
        if (!$channel) {
            return ['success' => false, 'error' => 'sms_channel_missing'];
        }

         
         
        $lock_name = 'ec_sms_chat_' . substr(hash('sha256', $phone), 0, 32);
        $lock = $this->db->query("SELECT GET_LOCK('" . $this->db->escape($lock_name) . "', 3) AS `locked`");
        if (!$lock || (int)($lock->row['locked'] ?? 0) !== 1) {
            return ['success' => false, 'error' => 'sms_conversation_busy', 'retryable' => true];
        }
        $transaction_open = false;
        try {
            $this->db->query('START TRANSACTION');
            $transaction_open = true;
            $messenger = new MessengerModel($this->registry);
            $contact = $messenger->findContact((int)$channel['channel_id'], $phone);
            if ($contact && (int)($contact['chat_id'] ?? 0) > 0) {
                $chat_id = (int)$contact['chat_id'];
                $chat = (new Session($this->registry))->getSessionById($chat_id);
                if (!$chat) {
                    $this->db->query('ROLLBACK');
                    $transaction_open = false;
                    return ['success' => false, 'error' => 'sms_chat_missing'];
                }
                $linked_customer_id = (int)($chat['customer_id'] ?? 0);
                if ($linked_customer_id > 0 && $linked_customer_id !== $customer_id) {
                    $this->db->query('ROLLBACK');
                    $transaction_open = false;
                    return ['success' => false, 'error' => 'phone_customer_conflict'];
                }
                if ($linked_customer_id === 0) {
                    $this->db->query(
                        "UPDATE `{$this->prefix}sessions` SET `customer_id` = " . (int)$customer_id . "
                         WHERE `chat_id` = " . $chat_id . " AND `customer_id` IS NULL"
                    );
                }
                $this->db->query('COMMIT');
                $transaction_open = false;
                return ['success' => true, 'chat_id' => $chat_id, 'channel' => $channel, 'contact' => $contact];
            }

            $session = new Session($this->registry);
            $chat_id = (int)$session->createSession('out_sms_' . bin2hex(random_bytes(8)), $display_name !== '' ? $display_name : $phone, [
                'source_provider' => SmsProvider::PROVIDER,
                'source_channel_id' => (int)$channel['channel_id'],
            ]);
            $this->db->query(
                "UPDATE `{$this->prefix}sessions` SET `customer_id` = " . (int)$customer_id . "
                 WHERE `chat_id` = " . $chat_id
            );
            $contact = $messenger->upsertContact(
                (int)$channel['channel_id'],
                SmsProvider::PROVIDER,
                $phone,
                $phone,
                $display_name !== '' ? $display_name : $phone,
                '',
                '',
                $chat_id,
                ['source' => 'scheduled_reminder'],
                true
            );
            if (!$contact) {
                $this->db->query('ROLLBACK');
                $transaction_open = false;
                return ['success' => false, 'error' => 'sms_contact_create_failed'];
            }
            $messenger->linkContactToChat((int)$contact['contact_id'], $chat_id);
            $session->updateSession($chat_id, ['external_contact_id' => (int)$contact['contact_id']]);
            $this->db->query('COMMIT');
            $transaction_open = false;
             
             
            $this->releaseLock($lock_name);
            $lock_name = '';
            (new SmsInboundFilterRefreshScheduler($this->registry))->enqueue();
            return ['success' => true, 'chat_id' => $chat_id, 'channel' => $channel, 'contact' => $contact];
        } catch (\Throwable $e) {
            if ($transaction_open) $this->db->query('ROLLBACK');
            return ['success' => false, 'error' => 'sms_conversation_failed', 'retryable' => true];
        } finally {
            $this->releaseLock($lock_name);
        }
    }

    private function releaseLock(string $lock_name): void {
        if (!preg_match('/^ec_sms_chat_[a-f0-9]{32}$/D', $lock_name)) return;
        try {
            $this->db->query("SELECT RELEASE_LOCK('" . $this->db->escape($lock_name) . "')");
        } catch (\Throwable $ignored) {
             
             
        }
    }
}
