<?php

namespace objects;

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

class user_price_overrides_o extends db
{
    use db_object_t;

    public int $user_id;
    public object_property $is_category;
    public object_property $product_or_category_id;
    public object_property $percentage;

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

    public function objectChanged(): void
    {
        // No need to invalidate the cache, since the user_price_overrides object is not cached
    }

    public function getObjectProperties(): void
    {
        $this->is_category = new object_property($this->table, $this->id, 'is_category', 'bool', true);
        $this->product_or_category_id = new object_property($this->table, $this->id, 'product_or_category_id', 'int', true);
        $this->percentage = new object_property($this->table, $this->id, 'percentage', 'int', true);
    }

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

    /**
     * Set a price override for the user
     * @param bool $is_category
     * @param int|string $product_or_category_id
     * @param int $percentage
     * @return $this
     */
    public function setPrice(bool $is_category, int|string $product_or_category_id, int $percentage): user_price_overrides_o
    {
        global $db;
        // If the user is not set, return the object
        if (!isset($this->user_id)) {
            return $this;
        }
        // Check if the record already exists
        $this->removePriceIfExist($is_category, $product_or_category_id);
        // If the percentage is 0, return the object
        if ($percentage === 0) {
            return $this;
        }
        // Create a new record in the database
        $sql = "INSERT INTO $this->table (user_id, is_category, product_or_category_id, percentage) VALUES ($this->user_id, " . (int)$is_category . ", '$product_or_category_id', $percentage)";
        $db->query($sql);
        return $this;
    }

    private function removePriceIfExist(bool $is_category, int|string $product_or_category_id): void
    {
        global $db;
        // Get the price override from the database
        $sql = "SELECT * FROM $this->table WHERE user_id = " . $this->user_id . " AND is_category = " . (int)$is_category . " AND product_or_category_id = '$product_or_category_id'";
        $result = $db->query($sql);

        if ($result->num_rows > 0) {
            // Remove the record from the database
            $sql = "DELETE FROM $this->table WHERE user_id = " . $this->user_id . " AND is_category = " . (int)$is_category . " AND product_or_category_id = '$product_or_category_id'";
            $db->query($sql);
        }
    }

    /**
     * Get the price override (PERCENTAGE) for the user
     * @param bool $is_category
     * @param int|string $product_or_category_id
     * @return int
     */
    public function getPrice(bool $is_category, int|string $product_or_category_id): int
    {
        global /** @var db $db */
        $db;
        $sql = "SELECT * FROM $this->table WHERE user_id = " . $this->user_id . " AND is_category = " . (int)$is_category . " AND product_or_category_id = ";
        // If the is_category is false, the product_or_category_id is a product_id
        if (!$is_category) {
            $product_or_category_id = (int)$product_or_category_id;
            $sql .= $product_or_category_id;
        } else {
            // If the is_category is true, the product_or_category_id is a category_id
            $product_or_category_id = $db->escape_string($product_or_category_id);
            $sql .= "'$product_or_category_id'";
        }
        // Get the price override from the database
        $result = $db->query($sql);

        $percentage = 0;

        if ($result->num_rows > 0) {
            // Return the percentage
            $percentage = $result->fetch_assoc()['percentage'];
        }
        // If the object is a product, check if the category has a discount set
        if (!$is_category) {
            $product = (new products_o())->getProductById($product_or_category_id);
            if ($product->apply_category_discount->value()) {
                // Get the economic user discount
                $economic_user_global_discount = (new users_o())->getUserById($this->user_id)->getEconomicCustomerDiscountPercentage();
                // Get the category discount
                $sql = "SELECT * FROM $this->table WHERE user_id = " . $this->user_id . " AND is_category = 1 AND product_or_category_id = '" . $product->category->value() . "'";
                $result = $db->query($sql);
                if ($result->num_rows > 0) {
                    $category_discount = $result->fetch_assoc()['percentage'];
                    // If the category discount is higher than the product discount, return the category discount
                    if ((int)$category_discount > (int)$percentage && (int)$category_discount > (int)$economic_user_global_discount) {
                        return $category_discount;
                    }
                }
                // If the economic user discount is higher than the product discount, return the economic user discount
                if ((int)$economic_user_global_discount > (int)$percentage) {
                    return $economic_user_global_discount;
                }
            }
        }
        return $percentage;
    }

    /**
     * Get all the price overrides for the user
     * @return array
     */
    public function getAllPrices(): array
    {
        global $db;
        // Get the customers global discount
        $economic_user_global_discount = (new users_o())->getUserById($this->user_id)->getEconomicCustomerDiscountPercentage();
        // Get all the price overrides for the user
        $sql = "SELECT * FROM $this->table WHERE user_id = " . $this->user_id;
        $result = $db->query($sql);
        $prices = [];
        if ($result->num_rows > 0) {
            while ($row = $result->fetch_assoc()) {
                // Parse the row
                $row['id'] = (int)$row['id'];
                $row['user_id'] = (int)$row['user_id'];
                $row['is_category'] = (bool)$row['is_category'];
                $row['product_or_category_id'] = (int)$row['product_or_category_id'];
                $row['percentage'] = (int)$row['percentage'];
                $row['created_at'] = (string)$row['created_at'];
                $row['updated_at'] = (string)$row['updated_at'];
                // Add the row to the list
                $prices[] = $row;
            }
        }
        // If the user has a global discount, add it to the list
        if ($economic_user_global_discount > 0) {
            $prices[] = [
                'id' => (int)999999,
                'user_id' => (int)$this->user_id,
                'is_category' => true,
                'product_or_category_id' => "global",
                'percentage' => (int)$economic_user_global_discount,
                'created_at' => "2021-01-01 00:00:00",
                'updated_at' => "2021-01-01 00:00:00"
            ];
        }
        return $prices;
    }
}