<?php

namespace dokuwiki\plugin\bez\mdl;

//ACL level defines
define('BEZ_AUTH_NONE', 0);
define('BEZ_AUTH_VIEWER', 2);
define('BEZ_AUTH_USER', 5);
define('BEZ_AUTH_LEADER', 10);
define('BEZ_AUTH_SYSADMIN', 15);   // Admin de sistema: ve proyectos, NO crea/edita/elimina
define('BEZ_AUTH_ADMIN', 20);

define('BEZ_PERMISSION_UNKNOWN', -1);
define('BEZ_PERMISSION_NONE', 0);
define('BEZ_PERMISSION_VIEW', 1);
define('BEZ_PERMISSION_CHANGE', 2);
define('BEZ_PERMISSION_DELETE', 3);


class Model {
    /** @var \helper_plugin_sqlite */
	protected $sqlite;

	/** @var \SQLite3 */
	protected $db;

    protected $level = BEZ_AUTH_NONE;

    /** @var array Grupos DokuWiki del usuario actual */
    protected $user_grps = [];

    protected $dw_auth, $user_nick, $action, $conf;

    /** @var ThreadFactory */
    protected $threadFactory;

    /** @var UserFactory  */
    protected $userFactory;

    /** @var LabelFactory */
    protected $labelFactory;

    /** @var Thread_commentFactory */
    protected $thread_commentFactory;

    /** @var TaskFactory */
    protected $taskFactory;

    /** @var Task_programFactory */
    protected $task_programFactory;

    /** @var Task_commentFactory */
    protected $task_commentFactory;

    /** @var Authentication_tokenFactory */
    protected $authentication_tokenFactory;

    /** @var SubscriptionFactory */
    protected $subscriptionFactory;

	public function __get($property) {
        $models = array('userFactory', 'threadFactory', 'labelFactory', 'thread_commentFactory', 'taskFactory', 'task_programFactory', 'task_commentFactory', 'authentication_tokenFactory', 'subscriptionFactory');
		if (in_array($property, $models) ||
            in_array($property, array('sqlite', 'db', 'acl', 'dw_auth', 'user_nick', 'action', 'conf', 'user_grps', 'level'))) {
			return $this->$property;
		}
	}

	public function factory($table) {
	    $prop = $table . 'Factory';

	    return $this->$prop;
    }

    protected function update_level($level) {
        if ($level > $this->level) {
            $this->level = $level;
        }
    }

    public function get_level() {
        return $this->level;
    }

    /**
     * Verifica si el usuario actual pertenece a un grupo DokuWiki
     */
    public function hasGroup($group) {
        return in_array($group, $this->user_grps);
    }

	public function __construct($dw_auth, $user_nick, $action, $skip_acl=false) {
        $this->dw_auth = $dw_auth;
        $this->user_nick = $user_nick;
		$this->action = $action;
        $this->conf = $action->getGlobalConf();

        $this->db_helper =  plugin_load('helper', 'bez_db');

        $this->sqlite = $this->db_helper->getDB();
        $this->db = $this->sqlite->getAdapter()->getPdo();
        $this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

        // Configurar busy_timeout de forma segura
        $busy_timeout_conf = $this->action->getConf('busy_timeout');
        $busy_timeout = abs((int)$busy_timeout_conf) * 1000; // Convertir a ms, asegurar valor positivo
        // Limitar a un maximo razonable (60 segundos)
        $busy_timeout = min($busy_timeout, 60000);
        // PRAGMA no soporta prepared statements, pero el valor ya esta sanitizado como entero
        $this->db->exec("PRAGMA busy_timeout = " . $busy_timeout);

        $this->userFactory = new UserFactory($this);

        $this->threadFactory = new ThreadFactory($this);

        $this->labelFactory = new LabelFactory($this);

        $this->thread_commentFactory = new Thread_commentFactory($this);

        $this->taskFactory = new TaskFactory($this);

        $this->task_programFactory = new Task_programFactory($this);

        $this->task_commentFactory = new Task_commentFactory($this);

        $this->authentication_tokenFactory = new Authentication_tokenFactory($this);

        $this->subscriptionFactory = new SubscriptionFactory($this);

        if ($skip_acl) {
            $this->update_level(BEZ_AUTH_ADMIN);
        } else {
            // Leer grupo admin configurable (default: 'bez_admin')
            $bez_admin_group = $this->action->getConf('admin_group');
            if (empty($bez_admin_group)) $bez_admin_group = 'bez_admin';

            $userd = $this->dw_auth->getUserData($this->user_nick);
            if ($userd !== false && is_array($userd['grps'])) {
                $grps = $userd['grps'];
                $this->user_grps = $grps;
                // Manager = DIOS (solo por grupo manager, asignado por managerprotect a usuarios sie*)
                if (in_array('manager', $grps)) {
                    $this->update_level(BEZ_AUTH_ADMIN);
                }
                // Director (grupo explícito) = acceso total a BEZ
                elseif (in_array('director', $grps)) {
                    $this->update_level(BEZ_AUTH_ADMIN);
                }
                // Admin group configurable (default: bez_admin) = líder de proyectos
                elseif (in_array($bez_admin_group, $grps)) {
                    $this->update_level(BEZ_AUTH_ADMIN);
                }
                // Admin DokuWiki = gestiona sistema, solo VE proyectos
                elseif (in_array('admin', $grps)) {
                    $this->update_level(BEZ_AUTH_SYSADMIN);
                }
                // bez_leader = liderazgo parcial
                elseif (in_array('bez_leader', $grps)) {
                    $this->update_level(BEZ_AUTH_LEADER);
                }
                else {
                    $this->update_level(BEZ_AUTH_USER);
                }
            } elseif (isset($_GET['t'])) {
                $page_id = $this->action->id();

                $user_tok = trim($_GET['t']);
                if (hash_equals($this->authentication_tokenFactory->get_token($page_id), $user_tok)) {
                    $this->update_level(BEZ_AUTH_VIEWER);
                }
            }
        }
    }
}
