<?php
namespace EasyChat\Model;

use EasyChat\Library\AppClock;









class ChatAssignment extends Base {

    






    public function assignIfMissing($chat_id, $manager_id, $assigned_by_manager_id = 0, $source = 'manual'): bool {
        $chat_id = (int)$chat_id;
        $manager_id = (int)$manager_id;
        $assigned_by_manager_id = max(0, (int)$assigned_by_manager_id);
        $source = $this->normalizeSource($source);
        if ($chat_id <= 0 || $manager_id <= 0) {
            return false;
        }

        $now = $this->db->escape((new AppClock($this->registry))->nowSql());
        $this->db->query(
            "INSERT INTO `{$this->prefix}chat_operator_assignments`
                (`chat_id`, `manager_id`, `assigned_by_manager_id`, `assignment_source`,
                 `assigned_at`, `last_activity_at`)
             SELECT s.`chat_id`, m.`id`, " . $assigned_by_manager_id . ",
                    '" . $this->db->escape($source) . "', '{$now}', '{$now}'
             FROM `{$this->prefix}sessions` s
             INNER JOIN `{$this->prefix}managers` m ON m.`id` = " . $manager_id . "
             WHERE s.`chat_id` = " . $chat_id . "
             LIMIT 1
             ON DUPLICATE KEY UPDATE `chat_id` = VALUES(`chat_id`)"
        );

        $changed = (int)$this->db->countAffected() === 1;
        if ($changed) {
            $this->touchChat($chat_id);
        }
        return $changed;
    }

    public function assign($chat_id, $manager_id, $assigned_by_manager_id = 0, $source = 'manual'): bool {
        $chat_id = (int)$chat_id;
        $manager_id = (int)$manager_id;
        $assigned_by_manager_id = max(0, (int)$assigned_by_manager_id);
        $source = $this->normalizeSource($source);
        if ($chat_id <= 0 || $manager_id <= 0) {
            return false;
        }

        $now = $this->db->escape((new AppClock($this->registry))->nowSql());
        $this->db->query(
            "INSERT INTO `{$this->prefix}chat_operator_assignments`
                (`chat_id`, `manager_id`, `assigned_by_manager_id`, `assignment_source`,
                 `assigned_at`, `last_activity_at`)
             SELECT s.`chat_id`, m.`id`, " . $assigned_by_manager_id . ",
                    '" . $this->db->escape($source) . "', '{$now}', '{$now}'
             FROM `{$this->prefix}sessions` s
             INNER JOIN `{$this->prefix}managers` m ON m.`id` = " . $manager_id . "
             WHERE s.`chat_id` = " . $chat_id . "
             LIMIT 1
             ON DUPLICATE KEY UPDATE
                `assigned_by_manager_id` = VALUES(`assigned_by_manager_id`),
                `assignment_source` = VALUES(`assignment_source`),
                `last_activity_at` = VALUES(`last_activity_at`)"
        );

        $changed = (int)$this->db->countAffected() > 0;
        if ($changed) {
            $this->touchChat($chat_id);
        }
        return $changed;
    }

    public function unassign($chat_id, $manager_id): bool {
        $chat_id = (int)$chat_id;
        $manager_id = (int)$manager_id;
        if ($chat_id <= 0 || $manager_id <= 0) {
            return false;
        }

        $this->db->query(
            "DELETE FROM `{$this->prefix}chat_operator_assignments`
             WHERE `chat_id` = " . $chat_id . " AND `manager_id` = " . $manager_id
        );
        $changed = (int)$this->db->countAffected() > 0;
        if ($changed) {
            $this->touchChat($chat_id);
        }
        return $changed;
    }

    public function unassignManager($manager_id): int {
        $manager_id = (int)$manager_id;
        if ($manager_id <= 0) {
            return 0;
        }

        $this->db->query(
            "DELETE FROM `{$this->prefix}chat_operator_assignments`
             WHERE `manager_id` = " . $manager_id
        );
        return (int)$this->db->countAffected();
    }

    


    public function getSnapshotsForChatIds(array $chat_ids, $current_manager_id = 0): array {
        $ids = $this->normalizeIds($chat_ids);
        if (!$ids) {
            return [];
        }

        $current_manager_id = max(0, (int)$current_manager_id);
        $snapshots = [];
        foreach ($ids as $chat_id) {
            $snapshots[$chat_id] = [
                'assignees' => [],
                'assigned_to_me' => false,
                'has_active_assignees' => false,
                'active_assignee_count' => 0,
            ];
        }

        $query = $this->db->query(
            "SELECT a.`chat_id`, a.`manager_id`, a.`assignment_source`,
                    a.`assigned_at`, a.`last_activity_at`,
                    m.`name`, m.`image`, m.`role`, m.`status`
             FROM `{$this->prefix}chat_operator_assignments` a
             INNER JOIN `{$this->prefix}managers` m ON m.`id` = a.`manager_id`
             WHERE a.`chat_id` IN (" . implode(',', $ids) . ")
             ORDER BY (m.`status` = 1) DESC, a.`last_activity_at` DESC, m.`name` ASC, m.`id` ASC"
        );

        foreach ($query->rows as $row) {
            $chat_id = (int)$row['chat_id'];
            if (!isset($snapshots[$chat_id])) {
                continue;
            }
            $manager_id = (int)$row['manager_id'];
            $active = (int)$row['status'] === 1;
            $snapshots[$chat_id]['assignees'][] = [
                'id' => $manager_id,
                'name' => (string)$row['name'],
                'image' => (string)($row['image'] ?? ''),
                'role' => (string)$row['role'],
                'active' => $active,
                'source' => (string)$row['assignment_source'],
            ];
            if ($active) {
                $snapshots[$chat_id]['has_active_assignees'] = true;
                $snapshots[$chat_id]['active_assignee_count']++;
                if ($manager_id === $current_manager_id) {
                    $snapshots[$chat_id]['assigned_to_me'] = true;
                }
            }
        }

        return $snapshots;
    }

    public function getSnapshot($chat_id, $current_manager_id = 0): array {
        $chat_id = (int)$chat_id;
        $snapshots = $this->getSnapshotsForChatIds([$chat_id], $current_manager_id);
        return $snapshots[$chat_id] ?? [
            'assignees' => [],
            'assigned_to_me' => false,
            'has_active_assignees' => false,
            'active_assignee_count' => 0,
        ];
    }

    public function getActiveManagerIds($chat_id): array {
        $chat_id = (int)$chat_id;
        if ($chat_id <= 0) {
            return [];
        }

        $query = $this->db->query(
            "SELECT a.`manager_id`
             FROM `{$this->prefix}chat_operator_assignments` a
             INNER JOIN `{$this->prefix}managers` m
                ON m.`id` = a.`manager_id` AND m.`status` = 1
             WHERE a.`chat_id` = " . $chat_id . "
             ORDER BY a.`manager_id` ASC"
        );
        $ids = [];
        foreach ($query->rows as $row) {
            $manager_id = (int)$row['manager_id'];
            if ($manager_id > 0) {
                $ids[] = $manager_id;
            }
        }
        return $ids;
    }

    public function isAssigned($chat_id, $manager_id, $active_only = false): bool {
        $chat_id = (int)$chat_id;
        $manager_id = (int)$manager_id;
        if ($chat_id <= 0 || $manager_id <= 0) {
            return false;
        }

        $join = $active_only
            ? " INNER JOIN `{$this->prefix}managers` m ON m.`id` = a.`manager_id` AND m.`status` = 1"
            : '';
        $query = $this->db->query(
            "SELECT 1
             FROM `{$this->prefix}chat_operator_assignments` a" . $join . "
             WHERE a.`chat_id` = " . $chat_id . "
               AND a.`manager_id` = " . $manager_id . "
             LIMIT 1"
        );
        return $query && $query->num_rows > 0;
    }

    private function normalizeIds(array $ids): array {
        $clean = [];
        foreach ($ids as $id) {
            $id = (int)$id;
            if ($id > 0) {
                $clean[$id] = $id;
            }
        }
        return array_values($clean);
    }

    private function normalizeSource($source): string {
        $source = strtolower(preg_replace('/[^a-z0-9_\-]/i', '', (string)$source));
        return in_array($source, ['manual', 'reply', 'history', 'system'], true)
            ? $source
            : 'manual';
    }

    private function touchChat(int $chat_id): void {
        $now = $this->db->escape((new AppClock($this->registry))->nowSql());
        $this->db->query(
            "UPDATE `{$this->prefix}sessions`
             SET `date_modified` = '{$now}'
             WHERE `chat_id` = " . $chat_id
        );
    }
}
