<?php

namespace Modules\Report;

use Modules\Report\Reports\BranchPerformanceReport;
use Modules\Report\Reports\CashMovementReport;
use Modules\Report\Reports\CategorizedProductsReport;
use Modules\Report\Reports\CostRevenueByOrderReport;
use Modules\Report\Reports\CostRevenueReportByProductReport;
use Modules\Report\Reports\IngredientUsageReport;
use Modules\Report\Reports\LowStockAlertsReport;
use Modules\Report\Reports\PaymentsReport;
use Modules\Report\Reports\ProductsPurchaseReport;
use Modules\Report\Reports\ProductTaxReport;
use Modules\Report\Reports\RegisterSummaryReport;
use Modules\Report\Reports\SalesByCashierReport;
use Modules\Report\Reports\SalesByCreatorReport;
use Modules\Report\Reports\SalesReport;
use Modules\Report\Reports\TaxReport;
use Modules\Report\Reports\UpcomingOrdersReport;

class ReportManager
{
    /**
     * instance of ReportsManagement
     *
     * @var ReportManager
     */
    private static ReportManager $instance;

    /**
     * Registered reports
     *
     * @var array
     */
    protected array $registeredReports = [];

    /**
     * Array of available reports.
     *
     * @var array
     */
    private array $reports = [
        SalesReport::class,
        ProductsPurchaseReport::class,
        TaxReport::class,
        ProductTaxReport::class,
        BranchPerformanceReport::class,
        PaymentsReport::class,
        IngredientUsageReport::class,
        LowStockAlertsReport::class,
        RegisterSummaryReport::class,
        CashMovementReport::class,
        SalesByCreatorReport::class,
        SalesByCashierReport::class,
        CategorizedProductsReport::class,
        UpcomingOrdersReport::class,
        CostRevenueByOrderReport::class,
        CostRevenueReportByProductReport::class,
    ];

    /**
     * Get instance from ReportManager
     *
     * @return ReportManager
     */
    public static function getInstance(): ReportManager
    {
        if (!isset(static::$instance)) {
            static::$instance = new static();
            static::$instance->register(true);
        }

        return static::$instance;
    }

    /**
     * Register groups
     *
     * @param bool $force ;
     * @return void
     */
    public function register(bool $force = false): void
    {
        if (count($this->registeredReports) == 0 || $force) {
            foreach ($this->reports as $report) {
                $object = new $report;
                $this->registeredReports[$object->key()] = $object;
            }
        }
    }

    /**
     * Determine if group exists
     *
     * @param string $key
     * @return bool
     */
    public function reportExists(string $key): bool
    {
        return array_key_exists($key, $this->registeredReports());
    }

    /**
     * Register single report
     *
     * @param string|null $key
     * @return Report|array
     */
    public function registeredReports(?string $key = null): array|Report
    {
        return is_null($key) ? $this->registeredReports : $this->registeredReports[$key];
    }
}
