<?php

namespace App\Libraries;

use Modules\Cancellation\Models\CancellationModel;
use Modules\Cancellation\Models\GlobalCancellationModel;

/**
 * Resolves cancellation slabs: global (passenger / online) vs company policy.
 *
 * Each row's `hours` is the notice window: charge applies while remaining hours until departure
 * are within that window (tier.hours >= remaining). Pick the smallest matching tier
 * (e.g. 10h left → 12h/35%, not 24h/20%).
 *
 * Company policies: if remaining is farther out than every tier (e.g. 47h left and max
 * tier is 24h), return null → 0% fee. Matches the original admin cancel behaviour and
 * how companies configure "fee within 24 hours".
 *
 * Global (passenger) policies: if farther out than every tier, fall back to the widest
 * tier (they usually define a large hours row for early-cancel %).
 */
class CancellationPolicy
{
    public static function findSlab(float $remainingHours, string $bookbyUserType, int $companyId): ?object
    {
        if ($remainingHours <= 0) {
            return null;
        }

        if ($bookbyUserType === 'passanger') {
            $model = new GlobalCancellationModel();
            $row = $model->select('*')
                ->where('hours >=', $remainingHours)
                ->orderBy('hours', 'ASC')
                ->first();
            if (empty($row)) {
                $row = $model->select('*')->orderBy('hours', 'DESC')->first();
            }

            return $row ?: null;
        }

        $model = new CancellationModel();
        $row = $model->select('*')
            ->where('hours >=', $remainingHours)
            ->where('company_id', $companyId)
            ->orderBy('hours', 'ASC')
            ->first();

        // No matching window → free cancel (do not fall back to max hours / lowest %).
        return $row ?: null;
    }

    /**
     * @return array{cancel_charge: float|int, refunded_amount: float|int}
     */
    public static function amountsFromSlab(?object $slab, float $totalAmount): array
    {
        if ($totalAmount <= 0) {
            return ['cancel_charge' => 0, 'refunded_amount' => 0];
        }
        if ($slab === null || $slab->charges === null || $slab->charges === '') {
            return ['cancel_charge' => 0, 'refunded_amount' => round($totalAmount)];
        }
        $percentage = (float) $slab->charges;
        $cancelCharge = round($totalAmount * $percentage / 100);
        $refunded = round($totalAmount - $cancelCharge);

        return [
            'cancel_charge' => $cancelCharge,
            'refunded_amount' => max(0, $refunded),
        ];
    }
}
