<?php

namespace classes;

use interfaces\redis_i;

class redis implements redis_i
{
    use \traits\redis_t;

    public function __construct()
    {
        global $REDIS_CONFIG;
        // Make sure the Redis configuration is set
        if (!isset($REDIS_CONFIG)) {
            throw new \Exception('Redis configuration is not set');
        }
        // Apply the Redis configuration
        $this->redis_host = $REDIS_CONFIG['host'];
        $this->redis_database = $REDIS_CONFIG['database'];
        $this->redis_password = $REDIS_CONFIG['password'];
    }


    /**
     * @inheritDoc
     */
    public function cache_department_booking_count(int $department_id, int $count): redis_i
    {
        // Cache the department booking count
        $this->set('department_booking_count_' . $department_id, $count);
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function get_department_booking_count(int $department_id): int|null
    {
        // Get the department booking count
        return $this->get('department_booking_count_' . $department_id);
    }

    /**
     * @inheritDoc
     */
    public function clear_department_booking_count(int $department_id): redis_i
    {
        // Clear the department booking count
        $this->delete('department_booking_count_' . $department_id);
        return $this;
    }


    /**
     * @inheritDoc
     */
    public function cache_department_webhook(int $department_id, string $webhook): self
    {
        // Cache the department webhook
        $this->set('department_webhook_' . $department_id, $webhook);
        $this->expire('department_webhook_' . $department_id, 300); // Expire in 5 minutes
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function get_department_webhook(int $department_id): string|null
    {
        // Get the department webhook
        return $this->get('department_webhook_' . $department_id);
    }

    /**
     * @inheritDoc
     */
    public function clear_department_webhook(int $department_id): self
    {
        // Clear the department webhook
        $this->delete('department_webhook_' . $department_id);
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function cache_department_name(int $department_id, string $department_name): self
    {
        // Cache the department name (If it is not empty or null)
        if (empty($department_name)) {
            $department_name = 'IS_EMPTY_OR_NULL';
            return $this;
        }
        // Set the department's name in the cache
        if ($this->get_department_name($department_id) === null) {
            $this->set('department_' . $department_id, json_encode(['name' => $department_name]
            ));
        };
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function get_department_name(int $department_id): string|null
    {
        // Get the department name
        $tmp_department = $this->get('department_' . $department_id) ?? null;
        if ($tmp_department === 'IS_EMPTY_OR_NULL' || $tmp_department === null) {
            return null;
        }
        $tmp_department = json_decode($tmp_department);
        // Return the department name
        return $tmp_department->name ?: $tmp_department['name'] ?? null;
    }

    /**
     * @inheritDoc
     */
    public function clear_department_name(int $department_id): self
    {
        // Clear the department name
        $this->delete('department_' . $department_id);
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function cache_economic_customer_discount_percentage(int $user_id, int $discount_percentage): self
    {
        // Cache the economic customer discount percentage
        $this->set('users_' . $user_id . '_economic_customer_discount_percentage', $discount_percentage);
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function get_economic_customer_discount_percentage(int $user_id): int|null
    {
        // Get the economic customer discount percentage
        return $this->get('users_' . $user_id . '_economic_customer_discount_percentage');
    }

    /**
     * @inheritDoc
     */
    public function clear_economic_customer_discount_percentage(int $user_id): self
    {
        // Clear the economic customer discount percentage
        $this->delete('users_' . $user_id . '_economic_customer_discount_percentage');
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function cache_customer_notes(int $user_id, array $customer_notes): self
    {
        // Cache the customer notes
        $this->set_array('users_' . $user_id . '_customer_notes', $customer_notes);
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function get_customer_notes(int $user_id): array|null
    {
        // Get the customer notes
        return $this->get_array('users_' . $user_id . '_customer_notes');
    }

    /**
     * @inheritDoc
     */
    public function clear_customer_notes(int $user_id): self
    {
        // Clear the customer notes
        $this->delete('users_' . $user_id . '_customer_notes');
        return $this;
    }


    /**
     * @inheritDoc
     */
    public function add_log(string $module, string $department, int $type, int $user_id, string $action, string $message): redis_i
    {
        // Get the current timestamp
        $timestamp = strtotime('now');
        // Get unique id for the log
        $log_id = uniqid();
        // Add the log to the cache
        $this->set_array('log_' . $log_id, [
            'id' => $log_id,
            'module' => $module,
            'department' => $department,
            'type' => $type,
            'user_id' => $user_id,
            'action' => $action,
            'message' => $message,
            'timestamp' => $timestamp
        ]);
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function get_logs(): array|null
    {
        // Get all logs from the cache
        return $this->get_arrays('log_*');
    }

    /**
     * @inheritDoc
     */
    public function clear_logs(): self
    {
        // Clear all logs from the cache
        $keys = $this->get_keys('log_*');
        foreach ( $keys as $key ) {
            $this->delete($key);
        }
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function get_department(int $department_id): array|null
    {
        // Get the department
        return $this->get_array('department_' . $department_id);
    }

    /**
     * @inheritDoc
     */
    public function clear_department(int $department_id): self
    {
        // Clear the departments
        $this->clear_departments();
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function clear_departments(): self
    {
        // Clear all departments from the cache
        $this->delete('departments');
        $keys = $this->get_keys('department_*');
        foreach ( $keys as $key ) {
            $this->delete($key);
        }
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function get_departments(): array|null
    {
        // Get all departments from the cache
        return $this->get_array('departments');
    }

    /**
     * @inheritDoc
     */
    public function cache_departments(array $departments): self
    {
        // Cache the departments
        foreach ( $departments as $department ) {
            $this->cache_department($department['id'], $department);
        }
        redis->set_array('departments', $departments);
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function cache_department(int $department_id, array $department): self
    {
        // Cache the department
        $this->set_array('department_' . $department_id, $department);
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function get_log_count(): int
    {
        // Get the log count
        return $this->count_keys('log_*');
    }

    /**
     * @inheritDoc
     */
    public function cache_token(string $token, array $row): self
    {
        // Cache the token
        $this->set_array('token_' . $token, $row);
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function get_token(string $token): array|null
    {
        // Get the token
        return $this->get_array('token_' . $token);
    }

    /**
     * @inheritDoc
     */
    public function clear_token(string $token): self
    {
        // Clear the token
        $this->delete('token_' . $token);
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function get_last_crond_run(string $task): int|null
    {
        // Get the last cron task
        return $this->get('last_cron_task_' . $task) ?? null;
    }

    /**
     * @inheritDoc
     */
    public function set_last_crond_run(string $task, int $time): self
    {
        // Set the last cron task
        $this->set('last_cron_task_' . $task, $time);
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function cache_user_id_from_customer_number(int $customer_number, int $user_id): self
    {
        // Cache the user id from customer number
        $this->set('user_id_from_customer_number_' . $customer_number, $user_id);
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function get_user_id_from_customer_number(int $customer_number): int|null
    {
        // Get the user id from customer number
        return $this->get('user_id_from_customer_number_' . $customer_number);
    }

    /**
     * @inheritDoc
     */
    public function clear_user_id_from_customer_number(int $customer_number): self
    {
        // Clear the user id from customer number
        $this->delete('user_id_from_customer_number_' . $customer_number);
        return $this;
    }

    public function expire(string $key, int $seconds): self
    {
        // Set the expiration time for a key
        $this->redis->expire($key, $seconds);
        return $this;
    }

    public function generateTemporaryCacheKey(): string
    {
        // Generate a temporary cache key
        return 'temporary_cache_' . uniqid();
    }

    public function mget(array $array_map): array
    {
        // Get multiple keys from Redis
        return $this->redis->mget($array_map);
    }
}