<?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\Api\Transformer;

use BookiFlex\Core\Model\Reservation\Reservation;
use BookiFlex\Core\Service\Aggregator\SummaryAggregator;

defined( 'ABSPATH' ) || exit;

/**
 * Transformer for reservation using SummaryAggregator
 */
class ReservationSummaryTransformer
{
    /**
     * Transform reservation with complete aggregation
     */
    public function transform(Reservation $reservation): array
    {
        $aggregator = new SummaryAggregator($reservation->getCurrency());

        // Add main reservation summary
        $aggregator->addSummary(
            $reservation->getCashier(),
            'reservation',
            'total',
            ['reservationId' => $reservation->getSid()]
        );

        // Add summaries for accommodation days
        foreach ($reservation->getAccommodationItems() as $index => $item) {
            $aggregator->addSummary(
                $item->getCashier(),
                'accommodation',
                'daily',
                [
                    'date' => $item->getDate()->format('Y-m-d'),
                    'itemId' => $item->getId(),
                    'accommodationType' => $item->getAccommodationTypeCode(),
                    'ratePlan' => $item->getRatePlanCode()
                ]
            );
        }

        // Add summaries for extra services
        foreach ($reservation->getExtraItems() as $item) {
            $context = [
                'itemId' => $item->getId(),
                'code' => $item->getCode(),
                'quantity' => $item->getQuantity(),
                'refundable' => $item->isRefundable(),
                'neutral' => $item->isNeutral()
            ];

            if ($item->getDate()) {
                $context['date'] = $item->getDate()->format('Y-m-d');
            }

            $aggregator->addSummary(
                $item->getCashier(),
                'extra',
                'item',
                $context
            );
        }

        // Add metadata
//        $aggregator->setMetadata([
//            'reservationNumber' => $reservation->getNumber(),
//            'status' => (string) $reservation->getStatus(),
//            'checkIn' => $reservation->getMinPossibleCheckInDateTime()?->format('c'),
//            'checkOut' => $reservation->getMaxPossibleCheckOutDateTime()?->format('c'),
//            'customer' => [
//                'name' => $reservation->getCustomer()->getFirstName() . ' ' . $reservation->getCustomer()->getLastName(),
//                'email' => $reservation->getCustomer()->getEmail()
//            ],
//            'accommodationDays' => count($reservation->getAccommodationItems()),
//            'extraServices' => count($reservation->getExtraItems()),
//            'createdAt' => $reservation->getCreatedAt()?->format('c')
//        ]);

        // Get aggregated result
        $aggregated = $aggregator->aggregate();

        return $aggregated->toArray();
    }

    /**
     * Transform only financial summary (lightweight version)
     */
    public function transformFinancialSummary(Reservation $reservation): array
    {
        $aggregator = new SummaryAggregator($reservation->getCurrency());

        // Collect all Cashier objects
        $aggregator->addSummary($reservation->getCashier(), 'reservation', 'total');
        $aggregator->addMultiple(
            array_map(fn($item) => $item->getCashier(), $reservation->getAccommodationItems()),
            'accommodation',
            'daily'
        );
        $aggregator->addMultiple(
            array_map(fn($item) => $item->getCashier(), $reservation->getExtraItems()),
            'extra',
            'item'
        );

        $aggregated = $aggregator->aggregate();

        // Return only financial part
        return [
            'currency' => $reservation->getCurrency(),
            'subtotal' => $aggregated->toArray()['subtotal'],
            'total' => $aggregated->toArray()['total'],
            'summary' => $aggregated->toArray()['summary'],
            'modifiers' => $this->simplifyModifiers($aggregated->toArray()['modifiers'])
        ];
    }

    /**
     * Get cancellation summary (for penalty calculation)
     */
    public function transformCancellationSummary(Reservation $reservation, ?int $days = null): array
    {
        $aggregator = new SummaryAggregator($reservation->getCurrency());

        // Base reservation amount
        $aggregator->addSummary(
            $reservation->getCashier(),
            'reservation',
            'base'
        );

        if ($days !== null) {
            // Add only first N days
            $count = 0;
            foreach ($reservation->getAccommodationItems() as $item) {
                if ($count < $days) {
                    $aggregator->addSummary(
                        $item->getCashier(),
                        'accommodation',
                        'cancellation',
                        ['day' => $count + 1, 'date' => $item->getDate()->format('Y-m-d')]
                    );
                    $count++;
                }
            }

            // Add non-refundable extra services
            foreach ($reservation->getExtraItems() as $item) {
                if (!$item->isRefundable()) {
                    $aggregator->addSummary(
                        $item->getCashier(),
                        'extra',
                        'non-refundable',
                        ['code' => $item->getCode()]
                    );
                }
            }
        }

        $aggregated = $aggregator->aggregate();
        $result = $aggregated->toArray();

        // Add penalty information
        $penalties = $reservation->calculatePenalties();
        $result['penalties'] = array_map(fn($penalty) => [
            'amount' => $penalty->getAmount()->getMinorAmount()->toInt(),
            'description' => $penalty->getDescription()
        ], $penalties);

        return $result;
    }

    /**
     * Simplified modifier format for API
     */
    private function simplifyModifiers(array $modifiers): array
    {
        return array_map(function($modifier) {
            return [
                'type' => $modifier['type'],
                'code' => $modifier['code'],
                'name' => $this->getModifierName($modifier),
                'amount' => $modifier['amount'],
                'display' => $this->formatModifierDisplay($modifier)
            ];
        }, $modifiers);
    }

    private function getModifierName(array $modifier): string
    {
        $names = [
            'vat' => 'VAT',
            'city_tax' => 'City Tax',
            'service_fee' => 'Service Fee',
            'cleaning_fee' => 'Cleaning Fee',
            'early_bird' => 'Early Bird Discount',
            'promo' => 'Promotional Discount',
            'loyalty' => 'Loyalty Discount'
        ];

        return $names[$modifier['code']] ?? ucfirst(str_replace('_', ' ', $modifier['code']));
    }

    private function formatModifierDisplay(array $modifier): string
    {
        $name = $this->getModifierName($modifier);

        if ($modifier['adjustmentType'] === 'PCT') {
            $name .= ' (' . $modifier['value'] . '%)';
        }

        return $name;
    }
}
