<?php
namespace EasyChat\Model;

use EasyChat\Library\PresenceService;
use EasyChat\Library\Security\PasswordCredentialService;

class Manager extends Base {

    public function __construct($registry) {
        parent::__construct($registry);
        $this->syncAdminFromConfig();
    }

    public function runMigrations() {
         
    }

    


    public function syncAdminFromConfig() {
        if (!defined('ADMIN_USERNAME') || !defined('ADMIN_PASSWORD')) {
            return;
        }

        $username = ADMIN_USERNAME;
        $password = ADMIN_PASSWORD;
        if ($password === '') {
            return;
        }
        $this->ensureStoredInitialPasswordHash($password);
        $password_customized = $this->isAdminPasswordCustomized();
        $credentials = new PasswordCredentialService();

         
        $query = $this->db->query("SELECT * FROM `{$this->prefix}managers` WHERE `id` = 1 LIMIT 1");

        if ($query->num_rows) {
            $admin = $query->row;
            $updates = array();

            if ($admin['username'] !== $username) {
                $updates[] = "`username` = '" . $this->db->escape($username) . "'";
            }

             
             
             
            if (!$password_customized && !$credentials->verify($password, (string)$admin['password']) && $this->hasStoredInitialPasswordHash()) {
                $this->markAdminPasswordCustomized();
                $password_customized = true;
            }

            if (!$password_customized && !$credentials->verify($password, (string)$admin['password'])) {
                $salt = bin2hex(random_bytes(16));
                $hashed = $credentials->hash($password);

                $updates[] = "`password` = '" . $this->db->escape($hashed) . "'";
                $updates[] = "`salt` = '" . $this->db->escape($salt) . "'";
            }

            $updates[] = "`status` = 1";

            if ($updates) {
                $this->db->query("UPDATE `{$this->prefix}managers` SET " . implode(', ', $updates) . " WHERE `id` = 1");
            }
        } else {
             
            $salt = bin2hex(random_bytes(16));
            $hashed = $credentials->hash($password);
            
            $this->db->query("INSERT INTO `{$this->prefix}managers` 
                (`id`, `username`, `password`, `salt`, `name`, `role`, `status`, `date_added`) 
                VALUES 
                (1, '" . $this->db->escape($username) . "', '" . $this->db->escape($hashed) . "', '" . $this->db->escape($salt) . "', 'Администратор', 'admin', 1, NOW())");
        }
    }

    public function getManagers() {
        $query = $this->db->query(
            "SELECT m.*,
                    SUM(CASE WHEN d.`status` = 'active' THEN 1 ELSE 0 END) AS `app_sessions`
             FROM `{$this->prefix}managers` m
             LEFT JOIN `{$this->prefix}app_devices` d ON d.`manager_id` = m.`id`
             GROUP BY m.`id`
             ORDER BY m.`id` ASC"
        );
        return $query->rows;
    }

    public function getActiveManagers() {
        $query = $this->db->query(
            "SELECT * FROM `{$this->prefix}managers`
             WHERE `status` = 1
             ORDER BY `id` ASC"
        );
        return $query->rows;
    }

    public function getActiveManagersForWidget() {
        $query = $this->db->query(
            "SELECT * FROM `{$this->prefix}managers`
             WHERE `status` = 1 AND `show_in_widget_header` = 1
             ORDER BY `last_active` DESC, `id` ASC
             LIMIT 4"
        );
        return $query->rows;
    }

    public function getManagerById($id) {
        $query = $this->db->query("SELECT * FROM `{$this->prefix}managers` WHERE `id` = " . (int)$id . " LIMIT 1");
        return $query->row;
    }

    public function getManagerByUsername($username) {
        $query = $this->db->query("SELECT * FROM `{$this->prefix}managers` WHERE `username` = '" . $this->db->escape($username) . "' LIMIT 1");
        return $query->row;
    }

    public function getActiveManagerByUsername($username) {
        $query = $this->db->query("SELECT * FROM `{$this->prefix}managers` WHERE `username` = '" . $this->db->escape($username) . "' AND `status` = 1 LIMIT 1");
        return $query->row;
    }

    public function getFirstActiveAdmin() {
        $query = $this->db->query("SELECT salt, password FROM `{$this->prefix}managers` WHERE `status` = 1 ORDER BY `id` ASC LIMIT 1");
        return $query->row;
    }

    public function getAvatar($id) {
        $query = $this->db->query("SELECT `image` FROM `{$this->prefix}managers` WHERE `id` = " . (int)$id . " LIMIT 1");
        return $query->row ? $query->row['image'] : '';
    }

    public function updateAvatar($id, $filename) {
        $this->db->query("UPDATE `{$this->prefix}managers` SET `image` = '" . $this->db->escape($filename) . "' WHERE `id` = " . (int)$id);
    }

    public function updatePasswordHash($id, $password_hash) {
        $password_hash = trim((string)$password_hash);
        if ((int)$id <= 0 || $password_hash === '') {
            throw new \InvalidArgumentException('manager_password_hash_invalid');
        }
        $salt = bin2hex(random_bytes(16));
        $this->db->query(
            "UPDATE `{$this->prefix}managers`
             SET `password` = '" . $this->db->escape($password_hash) . "',
                 `salt` = '" . $this->db->escape($salt) . "'
             WHERE `id` = " . (int)$id
        );
    }

    public function isUsernameTaken($username, $exclude_id = 0) {
        $query = $this->db->query("SELECT id FROM `{$this->prefix}managers` WHERE `username` = '" . $this->db->escape($username) . "' AND `id` != " . (int)$exclude_id . " LIMIT 1");
        return $query->num_rows > 0;
    }

    public function saveManager($id, $data) {
        $username = $data['username'];
        $name     = $data['name'];
        $role     = $data['role'];
        $status   = (int)$data['status'];
        $password = $data['password'] ?? '';
        $permission_delete_chats = (int)($data['permission_delete_chats'] ?? 0);
        $permission_manage_chat_assignments = (int)($data['permission_manage_chat_assignments'] ?? 0);
        $ai_suggestions_mode = $this->normalizeAiSuggestionsMode($data['ai_suggestions_mode'] ?? 'inherit');
        $show_in_widget_header = !empty($data['show_in_widget_header']) ? 1 : 0;
        $credentials = new PasswordCredentialService();

        if ($id > 0) {
            if ($id === 1) {
                $role = 'admin';
                $status = 1;
                $permission_delete_chats = 1;  
                $permission_manage_chat_assignments = 1;
            }

            $sql = "UPDATE `{$this->prefix}managers` SET 
                    `username` = '" . $this->db->escape($username) . "', 
                    `name` = '" . $this->db->escape($name) . "', 
                    `role` = '" . $this->db->escape($role) . "', 
                    `status` = {$status},
                    `permission_delete_chats` = {$permission_delete_chats},
                    `permission_manage_chat_assignments` = {$permission_manage_chat_assignments},
                    `ai_suggestions_mode` = '" . $this->db->escape($ai_suggestions_mode) . "',
                    `show_in_widget_header` = {$show_in_widget_header}";

            if ($password !== '') {
                $salt = bin2hex(random_bytes(16));
                $hashed = $credentials->hash($password);
                $sql .= ", `password` = '" . $this->db->escape($hashed) . "', `salt` = '" . $this->db->escape($salt) . "'";
            }

            $sql .= " WHERE `id` = {$id}";
            $this->db->query($sql);
            $this->touchAssignedChats($id);
            return (int)$id;
        } else {
            $salt = bin2hex(random_bytes(16));
            $hashed = $credentials->hash($password);

            $this->db->query("INSERT INTO `{$this->prefix}managers` 
                (`username`, `password`, `salt`, `name`, `role`, `status`, `permission_delete_chats`, `permission_manage_chat_assignments`, `ai_suggestions_mode`, `show_in_widget_header`, `date_added`)
                VALUES 
                ('" . $this->db->escape($username) . "', '" . $this->db->escape($hashed) . "', '" . $this->db->escape($salt) . "', '" . $this->db->escape($name) . "', '" . $this->db->escape($role) . "', {$status}, {$permission_delete_chats}, {$permission_manage_chat_assignments}, '" . $this->db->escape($ai_suggestions_mode) . "', {$show_in_widget_header}, NOW())");
            return (int)$this->db->getLastId();
        }
    }

    public function normalizeAiSuggestionsMode($mode) {
        $mode = (string)$mode;
        return in_array($mode, ['inherit', 'on', 'off'], true) ? $mode : 'inherit';
    }

    public function isAiSuggestionsAllowed($manager_id, array $settings = []) {
        if ((string)($settings['chat_ai_suggestions_status'] ?? '0') !== '1') {
            return false;
        }

        $manager = $this->getManagerById((int)$manager_id);
        if (!$manager || (int)($manager['status'] ?? 0) !== 1) {
            return false;
        }

        $mode = $this->normalizeAiSuggestionsMode($manager['ai_suggestions_mode'] ?? 'inherit');
        if ($mode === 'off') {
            return false;
        }
        if ($mode === 'on') {
            return true;
        }

        return (string)($settings['chat_ai_suggestions_default_mode'] ?? 'on') === 'on';
    }

    public function hasOnlineManagers($threshold_seconds = null) {
        $presence = new PresenceService($this->registry);
        return $presence->hasOnlineManagers($threshold_seconds);
    }

    public function isInitialAdminPassword($plain_password, $manager = null) {
        $plain_password = (string)$plain_password;
        if ($plain_password === '') {
            return false;
        }

        $setting = new Setting($this->registry);
        $initial_hash = (string)$setting->get('admin_initial_password_hash', '');
        if ($initial_hash !== '') {
            return hash_equals($initial_hash, hash('sha256', $plain_password));
        }

        if (defined('ADMIN_PASSWORD') && hash_equals((string)ADMIN_PASSWORD, $plain_password)) {
            return true;
        }

        return false;
    }

    public function isAdminPasswordCustomized() {
        $setting = new Setting($this->registry);
        return $setting->get('admin_password_customized', '0') === '1';
    }

    public function markAdminPasswordCustomized() {
        $setting = new Setting($this->registry);
        $setting->set('admin_password_customized', '1');
    }

    private function hasStoredInitialPasswordHash() {
        $setting = new Setting($this->registry);
        return $setting->get('admin_initial_password_hash', '') !== '';
    }

    private function ensureStoredInitialPasswordHash($plain_password) {
        $plain_password = (string)$plain_password;
        if ($plain_password === '') {
            return;
        }

        $setting = new Setting($this->registry);
        if ($setting->get('admin_initial_password_hash', '') !== '') {
            return;
        }

         
         
         
         
        $setting->set('admin_initial_password_hash', hash('sha256', $plain_password));
    }

    public function deleteManager($id) {
        $id = (int)$id;
        if ($id <= 0) {
            return;
        }
        $query = $this->db->query(
            "SELECT `chat_id`
             FROM `{$this->prefix}chat_operator_assignments`
             WHERE `manager_id` = " . $id
        );
        $chat_ids = [];
        foreach ($query->rows as $row) {
            $chat_id = (int)($row['chat_id'] ?? 0);
            if ($chat_id > 0) $chat_ids[$chat_id] = $chat_id;
        }
        $this->db->query("DELETE FROM `{$this->prefix}managers` WHERE `id` = " . $id);
         
         
         
        $this->db->query(
            "DELETE FROM `{$this->prefix}chat_operator_assignments`
             WHERE `manager_id` = " . $id
        );
         
         
         
         
        $this->db->query(
            "DELETE FROM `{$this->prefix}manager_notice_state`
             WHERE `manager_id` = " . $id
        );
        $this->db->query(
            "DELETE FROM `{$this->prefix}app_devices`
             WHERE `manager_id` = " . $id
        );
        try {
            $this->db->query("DELETE FROM `{$this->prefix}operator_message_drafts` WHERE `manager_id` = " . $id);
        } catch (\Throwable $ignored) {
             
             
        }
        if ($chat_ids) {
            $this->db->query(
                "UPDATE `{$this->prefix}sessions`
                 SET `date_modified` = NOW()
                 WHERE `chat_id` IN (" . implode(',', $chat_ids) . ")"
            );
        }
    }

    private function touchAssignedChats($manager_id) {
        $this->db->query(
            "UPDATE `{$this->prefix}sessions` s
             INNER JOIN `{$this->prefix}chat_operator_assignments` a
                ON a.`chat_id` = s.`chat_id`
             SET s.`date_modified` = NOW()
             WHERE a.`manager_id` = " . (int)$manager_id
        );
    }
}
