<?php
declare(strict_types=1);

namespace App\Modules\Reservations\Services;

use App\Core\App;
use App\Modules\Reservations\Models\Reservation;
use App\Modules\Facilities\Models\FacilityBlackoutDate;

class FacilityConflictDetector
{
    /**
     * Check for booking conflicts on a facility for a given date and time range.
     *
     * Returns an empty array when no conflicts exist, or an array of conflict
     * descriptions when overlaps are found.
     *
     * @return array<int, array{type: string, message: string}>
     */
    public static function checkConflicts(
        int $facilityId,
        string $date,
        string $startTime,
        string $endTime,
        ?int $excludeReservationId = null
    ): array {
        $conflicts = [];

        // 1. Check overlapping reservations
        $reservationConflicts = self::checkReservationConflicts(
            $facilityId, $date, $startTime, $endTime, $excludeReservationId
        );
        $conflicts = array_merge($conflicts, $reservationConflicts);

        // 2. Check overlapping rental bookings
        $rentalConflicts = self::checkRentalConflicts(
            $facilityId, $date, $startTime, $endTime
        );
        $conflicts = array_merge($conflicts, $rentalConflicts);

        // 3. Check facility blackout dates
        $blackoutConflicts = self::checkBlackoutConflicts(
            $facilityId, $date, $startTime, $endTime
        );
        $conflicts = array_merge($conflicts, $blackoutConflicts);

        return $conflicts;
    }

    /**
     * Check for overlapping reservations on the same facility/date.
     */
    private static function checkReservationConflicts(
        int $facilityId,
        string $date,
        string $startTime,
        string $endTime,
        ?int $excludeReservationId
    ): array {
        $conflicts = [];

        $query = (new \App\Core\QueryBuilder())
            ->table('reservations')
            ->where('facility_id', '=', $facilityId)
            ->where('reservation_date', '=', $date)
            ->whereRaw("`status` NOT IN ('cancelled', 'no_show')")
            ->whereRaw('(`start_time` < ? AND `end_time` > ?)', [$endTime, $startTime]);

        if ($excludeReservationId !== null) {
            $query = $query->whereRaw('`id` != ?', [$excludeReservationId]);
        }

        $rows = $query->get();

        foreach ($rows as $row) {
            $conflicts[] = [
                'type'    => 'reservation',
                'message' => sprintf(
                    'يوجد حجز متعارض (رقم %s) من %s إلى %s',
                    $row['reservation_number'] ?? '—',
                    $row['start_time'] ?? '',
                    $row['end_time'] ?? ''
                ),
            ];
        }

        return $conflicts;
    }

    /**
     * Check for overlapping rental bookings on the same facility/date.
     */
    private static function checkRentalConflicts(
        int $facilityId,
        string $date,
        string $startTime,
        string $endTime
    ): array {
        $conflicts = [];
        $db = App::getInstance()->db();

        // Check if rental_bookings table exists; skip gracefully if not
        try {
            $rows = $db->select(
                "SELECT * FROM `rental_bookings`
                 WHERE `facility_id` = ?
                   AND `booking_date` = ?
                   AND `status` NOT IN ('cancelled')
                   AND (`start_time` < ? AND `end_time` > ?)",
                [$facilityId, $date, $endTime, $startTime]
            );
        } catch (\Throwable) {
            // Table may not exist yet; silently skip
            return [];
        }

        foreach ($rows as $row) {
            $conflicts[] = [
                'type'    => 'rental',
                'message' => sprintf(
                    'يوجد حجز تأجير مؤسسي متعارض من %s إلى %s',
                    $row['start_time'] ?? '',
                    $row['end_time'] ?? ''
                ),
            ];
        }

        return $conflicts;
    }

    /**
     * Check for blackout dates on the facility.
     */
    private static function checkBlackoutConflicts(
        int $facilityId,
        string $date,
        string $startTime,
        string $endTime
    ): array {
        $conflicts = [];

        $rows = (new \App\Core\QueryBuilder())
            ->table('facility_blackout_dates')
            ->noSoftDelete()
            ->where('facility_id', '=', $facilityId)
            ->where('blackout_date', '=', $date)
            ->get();

        foreach ($rows as $row) {
            $bStart = $row['start_time'] ?? null;
            $bEnd   = $row['end_time'] ?? null;

            // Full-day blackout
            if (empty($bStart) && empty($bEnd)) {
                $conflicts[] = [
                    'type'    => 'blackout',
                    'message' => 'المرفق محجوب بالكامل في هذا التاريخ: ' . ($row['reason'] ?? ''),
                ];
                continue;
            }

            // Time-range blackout
            $bStart = $bStart ?? '00:00:00';
            $bEnd   = $bEnd ?? '23:59:59';

            if ($startTime < $bEnd && $endTime > $bStart) {
                $conflicts[] = [
                    'type'    => 'blackout',
                    'message' => sprintf(
                        'المرفق محجوب من %s إلى %s: %s',
                        $bStart,
                        $bEnd,
                        $row['reason'] ?? ''
                    ),
                ];
            }
        }

        return $conflicts;
    }
}
