<?php

namespace objects;

use classes\db;
use classes\object_property;
use Exception;
use traits\db_object_t;

class user_key_value_pairs_o extends db
{
    use db_object_t;

    public int $user_id;
    public object_property $var;
    public object_property $val;

    public function structure(): void
    {
        $this->setTable('user_key_value_pairs');
    }

    public function objectChanged(): void
    {
        // Since the user_key_value_pairs object is not cached, there is no need to invalidate the cache
    }

    public function getObjectProperties(): void
    {
        $this->var = new object_property($this->table, $this->id, 'var', 'string', true);
        $this->val = new object_property($this->table, $this->id, 'val', 'mixed', true);
    }

    public function setUser($user_id): user_key_value_pairs_o
    {
        $this->user_id = $user_id;
        return $this;
    }

    public function setValue($var, $val): user_key_value_pairs_o
    {
        global $db;
        self::requireSelected();
        // Avoid SQL injection
        $var = $db->escape_string($var);
        $val = $db->escape_string($val);
        // Check if the value exists in the database
        $exists = $this->getValue($var);
        // Create a new record in the database if it doesn't exist
        if ($exists !== null) {
            $sql = "UPDATE $this->table SET val = '$val' WHERE user_id = $this->user_id AND var = '$var'";
        } else {
            $sql = "INSERT INTO $this->table (user_id, var, val) VALUES ($this->user_id, '$var', '$val')";
        }
        $db->query($sql);
        return $this;
    }

    /**
     * @throws Exception
     */
    public function requireSelected(): void
    {
        if (empty($this->user_id)) {
            throw new Exception('The user id is not set!.');
        }
    }

    public function getValue($var): mixed
    {
        global $db;
        self::requireSelected();
        // Avoid SQL injection
        $var = $db->escape_string($var);
        // Get the record from the database
        $sql = "SELECT val FROM $this->table WHERE user_id = $this->user_id AND var = '$var'";
        $result = $db->query($sql);
        if ($result->num_rows > 0) {
            return $db->fetch_assoc($result)['val'];
        }
        return null;
    }

    public function deleteValue($var): user_key_value_pairs_o
    {
        global $db;
        self::requireSelected();
        // Avoid SQL injection
        $var = $db->escape_string($var);
        // Create a new record in the database
        $sql = "DELETE FROM $this->table WHERE user_id = $this->user_id AND var = '$var'";
        $db->query($sql);
        return $this;
    }

    public function getAllKeys(): array
    {
        global $db;
        self::requireSelected();
        // Get all the keys from the database
        $sql = "SELECT var, val FROM $this->table WHERE user_id = $this->user_id";
        $result = $db->query($sql);
        $result = $db->fetch_all($result);
        $keys = [];
        foreach ( $result as $row ) {
            $keys[$row['var']] = $row['val'];
        }
        return $keys;
    }

    public function getCustomerNumbersWithKey(array $keys): array
    {
        global $db;
        // Get all the users, and their customer numbers, with the given keys
        $sql = "SELECT user_id, val FROM $this->table WHERE var IN ('" . implode("','", $keys) . "')";
        $result = $db->query($sql);
        $result = $db->fetch_all($result);
        $user_ids = [];
        // Add the user ids to the array
        foreach ( $result as $row ) {
            // Check if the value is empty
            if (empty($row['val'])) {
                continue;
            }
            $user_ids[] = (int)$row['user_id'];
        }
        // Get the customer numbers from the users table
        $sql = "SELECT id, customer_number FROM users WHERE id IN (" . implode(',', $user_ids) . ")";
        $result = $db->query($sql);
        $result = $db->fetch_all($result);
        $customer_numbers = [];
        // Return the customer numbers
        foreach ( $result as $row ) {
            $customer_numbers[] = (int)$row['customer_number'];
        }
        return $customer_numbers;
    }

}