<?php

namespace goals\classes;

use goals\helpers\goals_criteria_type;

/**
 * Class goals
 * Main class for the goals module.
 */
class goals
{
    /**
     * The goals criteria
     * @var goals_criteria $criteria
     */
    public goals_criteria $criteria;

    /**
     * Constructor
     * @param goals_criteria|null $criteria
     */
    public function __construct(?goals_criteria $criteria = null)
    {
        $this->criteria = $criteria ?? new goals_criteria();
    }

    /**
     * Get the current result for the goal based on the criteria.
     * @return int|float
     */
    public function getResult(): int|float
    {
        // Delegate computation to criteria to keep logic centralized
        if (method_exists($this->criteria, 'currentResult')) {
            return $this->criteria->currentResult();
        }
        // Fallback for legacy behavior
        return match ($this->criteria->type) {
            goals_criteria_type::PRODUCT => $this->criteria->products->count($this->criteria),
            goals_criteria_type::REVENUE => 0,
            default => 0,
        };
    }

    /**
     * Get the percentage completion of the goal.
     * @return float
     */
    public function getPercentage(): float
    {
        if ($this->criteria->target <= 0) {
            return 0.0;
        }

        return ($this->getResult() / $this->criteria->target) * 100;
    }

    /**
     * Get the remaining value to reach the goal target.
     * @return int|float
     */
    public function getRemaining(): int|float
    {
        $remaining = $this->criteria->target - $this->getResult();
        return max(0, $remaining);
    }

    /**
     * Export to JSON (Used to be able to import/export goals)
     * @return string
     */
    public function exportToJson(): string
    {
        // Delegate export to the criteria to ensure canonical schema
        if (method_exists($this->criteria, 'toJson')) {
            return $this->criteria->toJson();
        }
        // Fallback (should not be used once toJson exists)
        return json_encode($this->criteria);
    }

    /**
     * Import from JSON (Used to be able to import/export goals)
     * @param string $json
     * @return goals
     * @throws \Exception If the JSON is invalid
     */
    public static function importFromJson(string $json): goals
    {
        $criteria = goals_criteria::fromJson($json);
        return new goals($criteria);
    }
}
