<?php
namespace EasyChat\Model;

use EasyChat\Library\AppClock;








class OperatorDraft extends Base {
    public static function tableSql(string $prefix): string {
        return "CREATE TABLE IF NOT EXISTS `{$prefix}operator_message_drafts` (
            `draft_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
            `manager_id` INT(11) NOT NULL,
            `chat_id` INT(11) NOT NULL,
            `composer_scope` VARCHAR(32) CHARACTER SET ascii COLLATE ascii_bin NOT NULL DEFAULT 'reply',
            `payload_ciphertext` MEDIUMTEXT NOT NULL,
            `content_hmac` CHAR(64) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
            `revision` INT UNSIGNED NOT NULL DEFAULT 1,
            `last_mutation_id` VARCHAR(80) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
            `context_message_id` INT(11) NOT NULL DEFAULT 0,
            `surface` VARCHAR(16) CHARACTER SET ascii COLLATE ascii_bin NOT NULL DEFAULT 'web',
            `date_added` DATETIME NOT NULL,
            `date_modified` DATETIME NOT NULL,
            UNIQUE KEY `uniq_operator_draft` (`manager_id`, `chat_id`, `composer_scope`),
            KEY `idx_operator_draft_recent` (`manager_id`, `date_modified`),
            KEY `idx_operator_draft_chat` (`chat_id`, `manager_id`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
    }

    public function begin(): void { $this->db->query('START TRANSACTION'); }
    public function commit(): void { $this->db->query('COMMIT'); }
    public function rollback(): void { $this->db->query('ROLLBACK'); }

    public function find(int $manager_id, int $chat_id, string $scope = 'reply', bool $for_update = false): array {
        if ($manager_id <= 0 || $chat_id <= 0) return [];
        $query = $this->db->query(
            "SELECT * FROM `{$this->prefix}operator_message_drafts`
             WHERE `manager_id` = {$manager_id} AND `chat_id` = {$chat_id}
               AND `composer_scope` = '" . $this->db->escape($scope) . "'
             LIMIT 1" . ($for_update ? ' FOR UPDATE' : '')
        );
        return ($query && $query->num_rows) ? $query->row : [];
    }

    public function rowsForChats(int $manager_id, array $chat_ids, string $scope = 'reply'): array {
        $ids = [];
        foreach ($chat_ids as $chat_id) {
            $chat_id = (int)$chat_id;
            if ($chat_id > 0) $ids[$chat_id] = $chat_id;
        }
        if ($manager_id <= 0 || !$ids) return [];
        $query = $this->db->query(
            "SELECT d.*, COALESCE(m.`max_message_id`, 0) AS `max_message_id`
             FROM `{$this->prefix}operator_message_drafts` d
             LEFT JOIN (
                 SELECT `chat_id`, MAX(`message_id`) AS `max_message_id`
                 FROM `{$this->prefix}messages`
                 WHERE `chat_id` IN (" . implode(',', $ids) . ")
                 GROUP BY `chat_id`
             ) m ON m.`chat_id` = d.`chat_id`
             WHERE d.`manager_id` = {$manager_id}
               AND d.`chat_id` IN (" . implode(',', $ids) . ")
               AND d.`composer_scope` = '" . $this->db->escape($scope) . "'"
        );
        $result = [];
        foreach (($query && is_array($query->rows)) ? $query->rows : [] as $row) {
            $result[(int)$row['chat_id']] = $row;
        }
        return $result;
    }

    public function insert(array $data): int {
        $now = (new AppClock($this->registry))->nowSql();
        $this->db->query(
            "INSERT INTO `{$this->prefix}operator_message_drafts` SET
             `manager_id` = " . (int)$data['manager_id'] . ",
             `chat_id` = " . (int)$data['chat_id'] . ",
             `composer_scope` = '" . $this->db->escape((string)$data['scope']) . "',
             `payload_ciphertext` = '" . $this->db->escape((string)$data['ciphertext']) . "',
             `content_hmac` = '" . $this->db->escape((string)$data['content_hmac']) . "',
             `revision` = 1,
             `last_mutation_id` = '" . $this->db->escape((string)$data['mutation_id']) . "',
             `context_message_id` = " . (int)$data['context_message_id'] . ",
             `surface` = '" . $this->db->escape((string)$data['surface']) . "',
             `date_added` = '" . $this->db->escape($now) . "',
             `date_modified` = '" . $this->db->escape($now) . "'"
        );
        return (int)$this->db->getLastId();
    }

    public function update(int $draft_id, int $revision, array $data): bool {
        $now = (new AppClock($this->registry))->nowSql();
        $this->db->query(
            "UPDATE `{$this->prefix}operator_message_drafts` SET
             `payload_ciphertext` = '" . $this->db->escape((string)$data['ciphertext']) . "',
             `content_hmac` = '" . $this->db->escape((string)$data['content_hmac']) . "',
             `last_mutation_id` = '" . $this->db->escape((string)$data['mutation_id']) . "',
             `context_message_id` = " . (int)$data['context_message_id'] . ",
             `surface` = '" . $this->db->escape((string)$data['surface']) . "',
             `revision` = `revision` + 1,
             `date_modified` = '" . $this->db->escape($now) . "'
             WHERE `draft_id` = {$draft_id} AND `revision` = {$revision}"
        );
        return (int)$this->db->countAffected() === 1;
    }

    public function deleteExact(int $manager_id, int $chat_id, int $revision, string $scope = 'reply'): bool {
        $this->db->query(
            "DELETE FROM `{$this->prefix}operator_message_drafts`
             WHERE `manager_id` = {$manager_id} AND `chat_id` = {$chat_id}
               AND `composer_scope` = '" . $this->db->escape($scope) . "'
               AND `revision` = {$revision}"
        );
        return (int)$this->db->countAffected() === 1;
    }
}
