<?php
/**
 * class/org.php — área de organización: una cuenta "organización" (is_org=1) puede
 * crear y gestionar cuentas normales (org_id = id de la organización) hasta un
 * límite (users.max_accounts), y ver su uso SIN coste.
 */
if (!defined('IN_APP')) { die('Acceso denegado'); }

class Org extends App
{
    /* ===================== Cuentas ===================== */

    /** Nº máximo de cuentas que puede crear la organización. */
    public function maxAccounts($orgId)
    {
        $orgId = (int)$orgId;
        $row = $this->db->query("SELECT max_accounts FROM users WHERE id_user=$orgId LIMIT 1")->fetch_assoc();
        return $row ? (int)$row['max_accounts'] : 0;
    }

    /** Nº de cuentas ya creadas por la organización. */
    public function countAccounts($orgId)
    {
        $orgId = (int)$orgId;
        return (int)$this->db->query("SELECT COUNT(*) c FROM users WHERE org_id=$orgId")->fetch_assoc()['c'];
    }

    /** Listado de cuentas de la organización (con nombre de plan). */
    public function accounts($orgId)
    {
        $orgId = (int)$orgId;
        $sql = "SELECT u.id_user, u.name, u.email, u.is_active, u.created_at, u.last_login_at, p.name AS plan_name
                FROM users u LEFT JOIN plans p ON p.id_plan = u.id_plan
                WHERE u.org_id = $orgId ORDER BY u.id_user ASC";
        return $this->db->query($sql)->fetch_all(MYSQLI_ASSOC);
    }

    /** Una cuenta concreta, garantizando que pertenece a la organización. */
    public function account($orgId, $id)
    {
        $stmt = $this->db->prepare('SELECT id_user, name, email, is_active, id_plan FROM users WHERE id_user=? AND org_id=? LIMIT 1');
        $stmt->bind_param('ii', $id, $orgId);
        $stmt->execute();
        $row = $stmt->get_result()->fetch_assoc();
        $stmt->close();
        return $row ?: null;
    }

    /** Planes disponibles para asignar a las cuentas. */
    public function plans()
    {
        $this->ensureSchema('plans');
        return $this->db->query('SELECT id_plan, name FROM plans ORDER BY name ASC')->fetch_all(MYSQLI_ASSOC);
    }

    /** Crea una cuenta normal bajo la organización (respeta el límite). */
    public function createAccount($orgId, $name, $email, $password, $id_plan)
    {
        $orgId = (int)$orgId;
        if ($this->countAccounts($orgId) >= $this->maxAccounts($orgId)) {
            $this->_error = App::t('org.limit_reached'); return false;
        }
        $name = trim($name); $email = trim($email);
        if ($name === '' || !filter_var($email, FILTER_VALIDATE_EMAIL) || strlen((string)$password) < 8) {
            $this->_error = App::t('user.invalid'); return false;
        }
        $hash = password_hash((string)$password, PASSWORD_DEFAULT);
        $plan = $id_plan ? (int)$id_plan : null;
        $loc  = App::locale();
        $stmt = $this->db->prepare('INSERT INTO users (name, email, pass_hash, locale, is_admin, is_active, is_org, org_id, id_plan, created_at) VALUES (?,?,?,?,0,1,0,?,?,NOW())');
        $stmt->bind_param('ssssii', $name, $email, $hash, $loc, $orgId, $plan);
        $ok = $stmt->execute();
        $stmt->close();
        if (!$ok) { $this->_error = App::t('auth.email_taken'); return false; }
        return true;
    }

    /** Actualiza una cuenta de la organización. */
    public function updateAccount($orgId, $id, $name, $email, $id_plan, $password = '')
    {
        if (!$this->account($orgId, $id)) { $this->_error = App::t('user.invalid'); return false; }
        $name = trim($name); $email = trim($email);
        if ($name === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) { $this->_error = App::t('user.invalid'); return false; }
        $plan = $id_plan ? (int)$id_plan : null;
        $id = (int)$id; $orgId = (int)$orgId;
        $stmt = $this->db->prepare('UPDATE users SET name=?, email=?, id_plan=? WHERE id_user=? AND org_id=?');
        $stmt->bind_param('ssiii', $name, $email, $plan, $id, $orgId);
        $ok = $stmt->execute();
        $stmt->close();
        if ($ok && strlen((string)$password) >= 8) {
            $hash = password_hash((string)$password, PASSWORD_DEFAULT);
            $st = $this->db->prepare('UPDATE users SET pass_hash=? WHERE id_user=? AND org_id=?');
            $st->bind_param('sii', $hash, $id, $orgId);
            $st->execute();
            $st->close();
        }
        return $ok;
    }

    /** Suspende/reactiva una cuenta de la organización. */
    public function setActive($orgId, $id, $active)
    {
        $a = $active ? 1 : 0; $id = (int)$id; $orgId = (int)$orgId;
        $stmt = $this->db->prepare('UPDATE users SET is_active=? WHERE id_user=? AND org_id=?');
        $stmt->bind_param('iii', $a, $id, $orgId);
        $stmt->execute();
        $stmt->close();
        if (!$a) $this->db->query("UPDATE users_sessions SET revoked=1 WHERE id_user=$id");
    }

    /** Elimina una cuenta de la organización (y sus datos asociados). */
    public function deleteAccount($orgId, $id)
    {
        if (!$this->account($orgId, $id)) return;
        $id = (int)$id;
        $this->db->query("DELETE FROM users_sessions WHERE id_user=$id");
        $this->db->query("DELETE FROM users_api_keys WHERE id_user=$id");
        $this->db->query("DELETE FROM users WHERE id_user=$id");
    }

    /* ===================== Uso (SIN coste) ===================== */

    /** IDs de las cuentas de la organización (para acotar las consultas de uso). */
    private function accountIds($orgId)
    {
        $orgId = (int)$orgId;
        $ids = array();
        $res = $this->db->query("SELECT id_user FROM users WHERE org_id=$orgId");
        while ($r = $res->fetch_assoc()) $ids[] = (int)$r['id_user'];
        return $ids;
    }

    /** Totales (histórico) de todas las cuentas de la organización. */
    public function summary($orgId)
    {
        $this->ensureSchema('kamicode_usage');
        $ids = $this->accountIds($orgId);
        if (!$ids) return array('req'=>0,'sess'=>0,'tin'=>0,'tout'=>0,'tcached'=>0);
        $in = implode(',', $ids);
        return $this->db->query("SELECT COUNT(*) req, COUNT(DISTINCT id_session) sess, COALESCE(SUM(tokens_in),0) tin, COALESCE(SUM(tokens_out),0) tout, COALESCE(SUM(tokens_cached),0) tcached FROM kamicode_usage WHERE id_user IN ($in)")->fetch_assoc();
    }

    /** Uso por cuenta (histórico, sin coste). */
    public function byUser($orgId)
    {
        $this->ensureSchema('kamicode_usage');
        $ids = $this->accountIds($orgId);
        if (!$ids) return array();
        $in = implode(',', $ids);
        $sql = "SELECT k.id_user, u.name, u.email, COUNT(*) req, COUNT(DISTINCT k.id_session) sess,
                       COALESCE(SUM(k.tokens_in),0) tin, COALESCE(SUM(k.tokens_out),0) tout, COALESCE(SUM(k.tokens_cached),0) tcached
                FROM kamicode_usage k LEFT JOIN users u ON u.id_user = k.id_user
                WHERE k.id_user IN ($in) GROUP BY k.id_user ORDER BY req DESC";
        return $this->db->query($sql)->fetch_all(MYSQLI_ASSOC);
    }

    /** Uso diario agregado de la organización (heatmap). */
    public function daily($orgId, $days = 371)
    {
        $this->ensureSchema('kamicode_usage');
        $ids = $this->accountIds($orgId);
        if (!$ids) return array();
        $in = implode(',', $ids);
        $start = date('Y-m-d', time() - (int)$days * 86400);
        $rows = $this->db->query("SELECT DATE(created_at) d, COUNT(*) req, COUNT(DISTINCT id_session) sess, COALESCE(SUM(tokens_in),0) tin, COALESCE(SUM(tokens_out),0) tout, COALESCE(SUM(tokens_cached),0) cached FROM kamicode_usage WHERE id_user IN ($in) AND created_at >= '$start' GROUP BY DATE(created_at)")->fetch_all(MYSQLI_ASSOC);
        $map = array();
        foreach ($rows as $r) $map[$r['d']] = $r;
        return $map;
    }

    /** Totales (histórico) de UNA cuenta de la organización (sin coste). */
    public function userStats($orgId, $id)
    {
        if (!$this->account($orgId, $id)) return array('req'=>0,'sess'=>0,'tin'=>0,'tout'=>0,'tcached'=>0);
        $id = (int)$id;
        return $this->db->query("SELECT COUNT(*) req, COUNT(DISTINCT id_session) sess, COALESCE(SUM(tokens_in),0) tin, COALESCE(SUM(tokens_out),0) tout, COALESCE(SUM(tokens_cached),0) tcached FROM kamicode_usage WHERE id_user=$id")->fetch_assoc();
    }

    /** Mapa ['id_modelo' => 'sobrenombre'] para no exponer modelos reales. */
    public function brands()
    {
        $this->ensureSchema('model_brands');
        $rows = $this->db->query("SELECT model, brand FROM model_brands")->fetch_all(MYSQLI_ASSOC);
        $map = array();
        foreach ($rows as $r) $map[$r['model']] = $r['brand'];
        return $map;
    }
}
