<?php
/**
 * BookiFlex Core
 *
 * @package    BookiFlex
 * @subpackage Core
 * @author     BookiFlex
 * @copyright  Copyright (c) 2025 BookiFlex
 * @license    GPL-2.0-or-later
 *
 * @link       https://bookiflex.com
 */


declare(strict_types=1);
namespace BookiFlex\Core\Service\Aggregator\ValueObject;

use Brick\Money\Money;

defined( 'ABSPATH' ) || exit;

/**
 * Value Object for aggregated summary
 */
class AggregatedSummary
{
    private string $currency;
    private Money $subtotal;
    private Money $total;
    private array $modifiers = [];
    private array $breakdown = [];
    private array $metadata = [];

    public function __construct(string $currency)
    {
        $this->currency = $currency;
        $this->subtotal = Money::zero($currency);
        $this->total = Money::zero($currency);
    }

    public function setSubtotal(Money $subtotal): void
    {
        $this->subtotal = $subtotal;
    }

    public function setTotal(Money $total): void
    {
        $this->total = $total;
    }

    public function setModifiers(array $modifiers): void
    {
        $this->modifiers = $modifiers;
    }

    public function setBreakdown(array $breakdown): void
    {
        $this->breakdown = $breakdown;
    }

    public function setMetadata(array $metadata): void
    {
        $this->metadata = $metadata;
    }

    /**
     * Convert to array for API
     */
    public function toArray(): array
    {
        return [
            'currency' => $this->currency,
            'subtotal' => $this->subtotal->getMinorAmount()->toInt(),
            'accommodationSubtotal' => $this->calculateBreakdownSubtotal('accommodation'),
            'total' => $this->total->getMinorAmount()->toInt(),
            'stayTotal' => $this->total->getMinorAmount()->toInt() - $this->calculateBreakdownTotal('extra'),
            'summary' => [
                'base' => $this->subtotal->getMinorAmount()->toInt(),
                'taxes' => $this->calculateModifierTotal('taxes'),
                'charges' => $this->calculateModifierTotal('charges'),
                'discounts' => $this->calculateModifierTotal('discounts')
            ],
            'modifiers' => $this->modifiers,
            'breakdown' => $this->formatBreakdown(),
            'metadata' => $this->metadata
        ];
    }

    /**
     * Get only modifiers of a specific type
     */
    public function getModifiersByType(string $type): array
    {
        return array_filter($this->modifiers, fn($m) => $m['type'] === $type);
    }

    /**
     * Get breakdown by source type
     */
    public function getBreakdownByType(string $type): array
    {
        return array_filter($this->breakdown, fn($b) => $b['type'] === $type);
    }

    private function calculateBreakdownTotal(string $type): int
    {
        $total = Money::zero($this->currency);
        foreach ($this->getBreakdownByType($type) as $entry) {
            $total = $total->plus($entry['total']);
        }
        return $total->getMinorAmount()->toInt();
    }

    private function calculateBreakdownSubtotal(string $type): int
    {
        $total = Money::zero($this->currency);
        foreach ($this->getBreakdownByType($type) as $entry) {
            $total = $total->plus($entry['subtotal']);
        }
        return $total->getMinorAmount()->toInt();
    }

    /**
     * Calculate total amount of modifiers by type
     */
    private function calculateModifierTotal(string $type): int
    {
        $total = 0;
        foreach ($this->getModifiersByType($type) as $modifier) {
            $total += $modifier['amount'];
        }
        return abs($total);
    }

    /**
     * Format breakdown for output
     */
    private function formatBreakdown(): array
    {
        $formatted = [];

        foreach ($this->breakdown as $key => $entry) {
            $formatted[$key] = [
                'type' => $entry['type'],
                'scope' => $entry['scope'],
                'context' => $entry['context'],
                'subtotal' => $entry['subtotal']->getMinorAmount()->toInt(),
                'total' => $entry['total']->getMinorAmount()->toInt(),
                'modifiers' => [
                    'taxes' => $entry['modifiers']['taxes']->getMinorAmount()->toInt(),
                    'charges' => $entry['modifiers']['charges']->getMinorAmount()->toInt(),
                    'discounts' => $entry['modifiers']['discounts']->getMinorAmount()->toInt()
                ],
                'itemsCount' => count($entry['items'])
            ];
        }

        return $formatted;
    }
}
