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

use BookiFlex\Core\Model\Reservation\Reservation;
use Brick\Money\Money;

defined( 'ABSPATH' ) || exit;

/**
 * Transforms Reservation domain models to arrays for WP_List_Table display.
 *
 * This transformer handles:
 * - Converting domain objects to flat associative arrays
 * - Formatting dates, times, and money values for display
 * - Merging prepayment data into rows
 * - Handling null safety for optional relations
 *
 * @package BookiFlex\Core\Admin\Transformer
 */
class ReservationTableListTransformer
{
    /**
     * Transform enriched service data to WP_List_Table format.
     *
     * Takes the enriched data structure from ReservationListService and converts
     * it to an array of associative arrays suitable for WP_List_Table rendering.
     *
     * @param array $data Service data with structure:
     *                    - reservations: Reservation[] - Domain models
     *                    - prepayments: array - Prepayment data by reservation ID
     * @return array[] Array of associative arrays for table rows
     */
    public function transform(array $data): array
    {
        $reservations = $data['reservations'] ?? [];
        $prepayments = $data['prepayments'] ?? [];

        if (empty($reservations)) {
            return [];
        }

        $rows = [];

        foreach ($reservations as $reservation) {
            $rows[] = $this->transformReservation($reservation, $prepayments);
        }

        return $rows;
    }

    /**
     * Transform single reservation with prepayment data.
     *
     * @param Reservation $reservation Reservation domain model
     * @param array $prepayments Prepayment data indexed by reservation ID
     * @return array Associative array for table row
     */
    private function transformReservation(Reservation $reservation, array $prepayments): array
    {
        $reservationId = $reservation->getId();
        $customer = $reservation->getCustomer();
        $paymentType = $reservation->getPaymentType();
        $group = $reservation->getGroup();

        // Get check-in/out dates from accommodation items
        $checkInDate = $reservation->getMinPossibleCheckInDateTime();
        $checkOutDate = $reservation->getMaxPossibleCheckOutDateTime();

        // Get prepayment data or defaults
        $prepaymentData = $prepayments[$reservationId] ?? [
            'prepayment' => Money::zero($reservation->getCurrency()),
            'paid' => Money::zero($reservation->getCurrency()),
        ];

        return [
            // Basic reservation data
            'id' => $reservationId,
            'number' => $reservation->getNumber(),
            'status' => (string) $reservation->getStatus(),
            'currency' => $reservation->getCurrency(),
            'language' => $reservation->getLanguage(),

            // Customer data
            'first_name' => $customer?->getFirstName() ?? '',
            'last_name' => $customer?->getLastName() ?? '',
            'email' => $customer?->getEmail() ?? '',

            // Dates and times (raw strings for backward compatibility)
            'check_in_date' => $checkInDate?->format('Y-m-d') ?? '',
            'check_out_date' => $checkOutDate?->format('Y-m-d') ?? '',

            // Dates and times (pre-formatted for display)
            'check_in_datetime' => $checkInDate,
            'check_out_datetime' => $checkOutDate,
            'length_of_stay' => $reservation->getLengthOfStay(),

            // Financial data (raw for sorting/filtering)
            'total_amount' => $reservation->getTotalAmount()->getMinorAmount()->toInt(),
            // Financial data (pre-formatted for display)
            'total_amount_formatted' => $reservation->getTotalAmount()->formatTo('en'),
            'prepayment' => $prepaymentData['prepayment'],
            'paid' => $prepaymentData['paid'],

            // Payment type
            'payment_type' => $paymentType?->getName() ?? '',
            'payment_type_id' => $paymentType?->getId(),

	        // Accommodation
	        'accommodation_name' => $reservation->getAccommodationItems()[0]->getName(),

            // Group info
            'group_id' => $group?->getId(),
            'is_group' => $group ? 'Yes' : 'No',
            'reservation_count' => $this->getReservationCount($reservation, $group),

            // Metadata (raw for backward compatibility)
            'special_request' => $reservation->getSpecialRequest(),
            'created_at' => $reservation->getCreatedAt()->format('Y-m-d H:i:s'),
            'updated_at' => $reservation->getUpdatedAt()?->format('Y-m-d H:i:s') ?? '',
            // Metadata (pre-formatted for display)
            'created_at_display' => $reservation->getCreatedAt()->format('Y-m-d H:i'),
        ];
    }

    /**
     * Get reservation count for group display.
     *
     * @param Reservation $reservation
     * @param mixed $group GroupReservation or null
     * @return int Count of reservations in group (1 if not grouped)
     */
    private function getReservationCount(Reservation $reservation, $group): int
    {
        if ($group === null) {
            return 1;
        }

        try {
            $reservations = $group->getReservations();
            return is_countable($reservations) ? count($reservations) : 1;
        } catch (\Throwable $e) {
            return 1;
        }
    }
}
