<?php

class LSD_Cart extends LSD_Base
{
    protected $cookie_name = 'lsd_cart_id';
    protected $option_prefix = 'lsd_cart_';

    protected function get(): array
    {
        $cart_id = $this->get_id();
        $cart = get_option($this->option_prefix . $cart_id, []);

        if (!is_array($cart)) $cart = [];
        if (!isset($cart['items']) || !is_array($cart['items'])) $cart['items'] = [];
        if (!isset($cart['fees']) || !is_array($cart['fees'])) $cart['fees'] = [];
        if (!isset($cart['coupon']) || !is_array($cart['coupon'])) $cart['coupon'] = [];

        return $cart;
    }

    protected function save(array $cart): void
    {
        $cart_id = $this->get_id();
        update_option($this->option_prefix . $cart_id, $cart, false);
    }

    public function get_items(): array
    {
        $cart = $this->get();
        return $cart['items'];
    }

    public function get_fees(): array
    {
        $cart = $this->get();
        return $cart['fees'];
    }

    public function add(int $plan_id, ?string $tier_id = null, array $meta = []): void
    {
        $cart = $this->get();

        // Tier ID
        if ($tier_id === null || $tier_id === '') $tier_id = (new LSD_Payments_Plan($plan_id))->get_default_tier_id();
        else $tier_id = sanitize_text_field($tier_id);

        // Item ID
        $id = function_exists('wp_generate_uuid4') ? wp_generate_uuid4() : md5(uniqid('lsd', true));

        $cart['items'][$id] = [
            'plan_id' => $plan_id,
            'tier_id' => $tier_id,
            'meta' => $meta,
        ];

        $this->save($cart);
    }

    public function set_fees(array $fees): void
    {
        $cart = $this->get();
        $cart['fees'] = $fees;

        $this->save($cart);
    }

    public function clear_fees(): void
    {
        $cart = $this->get();
        $cart['fees'] = [];

        $this->save($cart);
    }

    public function remove(string $id): void
    {
        $cart = $this->get();

        if (isset($cart['items'][$id]))
        {
            unset($cart['items'][$id]);
            $this->save($cart);
        }
    }

    public function update(string $id, string $tier_id): void
    {
        $cart = $this->get();

        if (isset($cart['items'][$id]))
        {
            $cart['items'][$id]['tier_id'] = sanitize_text_field($tier_id);
            $this->save($cart);
        }
    }

    protected function get_id(): string
    {
        if (isset($_COOKIE[$this->cookie_name]) && $_COOKIE[$this->cookie_name])
            return sanitize_text_field($_COOKIE[$this->cookie_name]);

        $cart_id = function_exists('wp_generate_uuid4') ? wp_generate_uuid4() : md5(uniqid('lsd', true));

        if (!headers_sent()) setcookie($this->cookie_name, $cart_id, time() + DAY_IN_SECONDS * 30, COOKIEPATH, COOKIE_DOMAIN);
        $_COOKIE[$this->cookie_name] = $cart_id;

        return $cart_id;
    }

    public function is_empty(): bool
    {
        return !count($this->get_items()) && !count($this->get_fees());
    }

    public function get_coupon(): string
    {
        $cart = $this->get();
        return $cart['coupon']['code'] ?? '';
    }

    public function add_coupon(string $code): void
    {
        $cart = $this->get();
        $cart['coupon'] = [
            'code' => sanitize_text_field($code),
        ];

        $this->save($cart);
    }

    public function remove_coupon(): void
    {
        $cart = $this->get();
        $cart['coupon'] = [];

        $this->save($cart);
    }

    public function clear(): void
    {
        $cart_id = $this->get_id();
        delete_option($this->option_prefix . $cart_id);

        if (!headers_sent()) setcookie($this->cookie_name, '', time() - DAY_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN);
        unset($_COOKIE[$this->cookie_name]);
    }

    public function get_sub_total()
    {
        $items = $this->get_items();
        $fees = $this->get_fees();

        $sub_total = 0;
        foreach ($items as $item)
        {
            $plan_id = (int) ($item['plan_id'] ?? 0);
            $tier_id = $item['tier_id'] ?? '';

            // Plan
            $plan = new LSD_Payments_Plan($plan_id, $tier_id);

            // Subtotal
            $sub_total += $plan->get_price();
        }

        foreach ($fees as $fee)
        {
            $sub_total += isset($fee['amount']) ? (float) $fee['amount'] : 0;
        }

        return $sub_total;
    }

    public function apply_coupon(): array
    {
        $coupon_code = $this->get_coupon();
        $coupon = $coupon_code ? new LSD_Payments_Coupon($coupon_code) : null;

        // Subtotal
        $subtotal = $this->get_sub_total();

        // Discount
        $discount = $coupon ? $coupon->calculate($subtotal) : 0;

        // Total
        $total = max($subtotal - $discount, 0);

        // Format
        $discount = round($discount, 2);
        $total = round($total, 2);

        return [$total, $discount];
    }
}
