<?php
namespace EasyChat\Library\Crm;

final class CrmDeliveryRepository {
    private $db;
    private $prefix;

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

    public function begin(int $connection_id, int $chat_id, int $message_id, string $operation, string $marker, string $payload_hash): array {
        $operation = $this->db->escape(substr($operation, 0, 32));
        $marker = $this->db->escape(substr($marker, 0, 64));
        $payload_hash = $this->db->escape(substr($payload_hash, 0, 64));
        $this->db->query("INSERT INTO `{$this->prefix}crm_message_deliveries` (`connection_id`,`chat_id`,`message_id`,`operation`,`state`,`idempotency_marker`,`payload_hash`,`attempts`,`date_added`,`date_modified`) VALUES ({$connection_id},{$chat_id},{$message_id},'{$operation}','inflight','{$marker}','{$payload_hash}',1,NOW(),NOW()) ON DUPLICATE KEY UPDATE `state`=IF(`state` IN ('succeeded','uncertain'),`state`,'inflight'),`attempts`=`attempts`+1,`date_modified`=NOW()");
        return $this->get($connection_id, $chat_id, $message_id, $operation);
    }

    public function succeeded(int $connection_id, int $chat_id, int $message_id, string $operation, string $external_operation_id = ''): void {
        $operation = $this->db->escape(substr($operation, 0, 32));
        $external_operation_id = $this->db->escape(substr($external_operation_id, 0, 64));
        $this->db->query("UPDATE `{$this->prefix}crm_message_deliveries` SET `state`='succeeded',`external_operation_id`='{$external_operation_id}',`last_error`='',`finished_at`=NOW(),`date_modified`=NOW() WHERE `connection_id`={$connection_id} AND `chat_id`={$chat_id} AND `message_id`={$message_id} AND `operation`='{$operation}'");
    }

    public function failed(int $connection_id, int $chat_id, int $message_id, string $operation, string $error, bool $uncertain, int $http_status = 0): void {
        $operation = $this->db->escape(substr($operation, 0, 32));
        $state = $uncertain ? 'uncertain' : 'failed';
        $error = $this->db->escape(substr(preg_replace('#https://[^\s]+#i', '[url hidden]', $error), 0, 500));
        $this->db->query("UPDATE `{$this->prefix}crm_message_deliveries` SET `state`='{$state}',`last_http_status`=" . max(0, $http_status) . ",`last_error`='{$error}',`date_modified`=NOW() WHERE `connection_id`={$connection_id} AND `chat_id`={$chat_id} AND `message_id`={$message_id} AND `operation`='{$operation}'");
    }

    private function get(int $connection_id, int $chat_id, int $message_id, string $operation): array {
        $query = $this->db->query("SELECT * FROM `{$this->prefix}crm_message_deliveries` WHERE `connection_id`={$connection_id} AND `chat_id`={$chat_id} AND `message_id`={$message_id} AND `operation`='{$operation}' LIMIT 1");
        return $query && $query->row ? $query->row : array();
    }
}
