<?php

declare(strict_types=1);

namespace Plugin\tnt_stabila_shop\src\Services;

use JTL\Cache\JTLCacheInterface;
use JTL\Shop;
use Plugin\tnt_stabila_shop\src\Helper\Formatter;
use Plugin\tnt_stabila_shop\src\Helper\MathHelper;
use Plugin\tnt_stabila_shop\src\Repositories\DatabaseRepository;
use Plugin\tnt_stabila_shop\src\Repositories\SessionRepository;

class SalesService
{
    use Formatter;

    public function __construct(
        protected DatabaseRepository $database,
        protected SessionRepository $session,
        protected JTLCacheInterface|null $cache = null
    ) {
        $this->cache = $cache ?? Shop::Container()->getCache();
    }

    /**
     * Returns the data for a metric item based on the type.
     *
     * @param string $type The type of metric item ('orders', 'customers').
     * @return object{icon: object{name: string, viewBox: string}, title: string, total: string,
     *     changeType: string, changeAmount: string, totalLastXDays: string, timeFrame: int}|null
     */
    public function getMetricItemData(string $type): object|null
    {
        return match ($type) {
            'orders'    => $this->getBasicOrderMetrics(),
            'customers' => $this->getBasicCustomerMetrics(),
            default => null,
        };
    }

    /**
     * @return object{icon: object{name: string, viewBox: string}, title: string, total: string,
     *     changeType: string, changeAmount: string, totalLastXDays: string, timeFrame: int}
     */
    public function getBasicCustomerMetrics(): object
    {
        $days               = 30;
        $totalCustomers     = $this->database->getTotalCustomers();
        $customersLastXDays = $this->database->getTotalCustomersXLastDays($days);
        // Limited by the last 2 years
        $monthlyCustomerTotals = $this->database->getMonthlyCustomerTotals();
        $performance           = MathHelper::calcPerformance($customersLastXDays, $monthlyCustomerTotals);
        $changeType            = 'changeUp';
        if ($customersLastXDays > 0 && $customersLastXDays < $performance->average) {
            $changeType = 'changeDown';
        }

        return (object)[
            'icon'           => (object)['name' => 'users', 'viewBox' => '0 0 24 24'],
            'title'          => \__('Customers'),
            'total'          => self::numberFormat($totalCustomers, 0),
            'changeType'     => $changeType,
            'changeAmount'   => self::numberFormat($performance->performance, 2, '%'),
            'totalLastXDays' => ' (+' . self::numberFormat($customersLastXDays, 0, '🙋') . ')',
            'timeFrame'      => $days,
        ];
    }

    /**
     * @return object{icon: object{name: string, viewBox: string}, title: string, total: string,
     *     changeType: string, changeAmount: string, totalLastXDays: string, timeFrame: int}
     */
    public function getBasicOrderMetrics(): object
    {
        $days            = 30;
        $totalOrders     = $this->database->getTotalOrders();
        $ordersLastXDays = $this->database->getTotalOrdersXLastDays($days);
        // Limited by the last 2 years
        $monthlyOrderTotals = $this->database->getMonthlyOrderTotals();
        $performance        = MathHelper::calcPerformance($ordersLastXDays, $monthlyOrderTotals);
        $changeType         = 'changeUp';
        if ($ordersLastXDays > 0 && $ordersLastXDays < $performance->average) {
            $changeType = 'changeDown';
        }

        return (object)[
            'icon'           => (object)['name' => 'cart', 'viewBox' => '0 0 24 24'],
            'title'          => \__('Orders'),
            'total'          => self::numberFormat($totalOrders, 0),
            'changeType'     => $changeType,
            'changeAmount'   => self::numberFormat($performance->performance, 2, '%'),
            'totalLastXDays' => ' (+' . self::numberFormat($ordersLastXDays, 0, '🛒') . ')',
            'timeFrame'      => $days,
        ];
    }

    /**
     * Returns the average monthly sales compared to this month.
     *
     * @return object{changeType: string, changeAmount: string, total: float, target: float,
     *     revenue: string, today: string}
     */
    public function getMonthlyAverageSales(): object
    {
        $monthlyTotals  = $this->database->getMonthlyOrderTotalAverage();
        $totalThisMonth = $this->database->getOrdersTotalThisMonth();
        $performance    = MathHelper::calcPerformance($totalThisMonth, $monthlyTotals);
        $changeType     = 'changeUp';
        if ($totalThisMonth < $performance->average) {
            $changeType = 'changeDown';
        }

        return (object)[
            'changeType'   => $changeType,
            'changeAmount' => self::numberFormat($performance->performance, 2, '%'),
            'total'        => $performance->average,
            'target'       => $totalThisMonth,
            'revenue'      => '',
            'today'        => '',
        ];
    }
}
