<?php
declare(strict_types=1);

namespace App\Modules\Facilities\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\Facilities\Models\Facility;
use App\Modules\Facilities\Models\FacilityTimeSlot;
use App\Modules\Facilities\Models\FacilityBlackoutDate;
use App\Modules\Disciplines\Models\SportDiscipline;

class FacilityController extends Controller
{
    /**
     * List all facilities with type filter tabs, location filter, search, and pagination.
     */
    public function index(Request $request): Response
    {
        $filters = [
            'q'              => trim((string) $request->get('q', '')),
            'facility_type'  => trim((string) $request->get('facility_type', '')),
            'location'       => trim((string) $request->get('location', '')),
            'linked_discipline_id' => trim((string) $request->get('linked_discipline_id', '')),
        ];

        $page = max(1, (int) $request->get('page', 1));
        $result = Facility::search($filters, 25, $page);

        return $this->view('Facilities.Views.index', [
            'facilities'  => $result['data'],
            'pagination'  => $result['pagination'],
            'filters'     => $filters,
            'types'       => Facility::getTypes(),
            'locations'   => Facility::getLocations(),
            'disciplines' => SportDiscipline::allActive(),
        ]);
    }

    /**
     * Show the create facility form.
     */
    public function create(Request $request): Response
    {
        return $this->view('Facilities.Views.create', [
            'types'       => Facility::getTypes(),
            'locations'   => Facility::getLocations(),
            'disciplines' => SportDiscipline::allActive(),
        ]);
    }

    /**
     * Validate and store a new facility.
     */
    public function store(Request $request): Response
    {
        $nameAr       = trim((string) $request->post('name_ar', ''));
        $nameEn       = trim((string) $request->post('name_en', ''));
        $code         = trim((string) $request->post('code', ''));
        $facilityType = trim((string) $request->post('facility_type', ''));
        $location     = trim((string) $request->post('location', ''));
        $capacity     = (int) $request->post('capacity', 0);
        $rateM        = (float) $request->post('hourly_rate_member', 0);
        $rateNM       = (float) $request->post('hourly_rate_nonmember', 0);
        $rateMPM      = (float) $request->post('hourly_rate_member_pm', 0);
        $rateNMPM     = (float) $request->post('hourly_rate_nonmember_pm', 0);
        $disciplineId = $request->post('linked_discipline_id', '');
        $disciplineId = $disciplineId !== '' ? (int) $disciplineId : null;

        // Auto-generate code if empty
        if ($code === '') {
            $typePrefix = strtoupper(substr($facilityType ?: 'FAC', 0, 5));
            $code = $typePrefix . '_' . strtoupper(substr(preg_replace('/[^A-Z0-9]/i', '', $nameEn ?: $nameAr), 0, 10)) . '_' . time() % 10000;
        }
        $code = strtoupper($code);

        // Validation
        $errors = [];
        if ($nameAr === '' || mb_strlen($nameAr) < 2) {
            $errors[] = 'اسم المرفق بالعربي مطلوب (حرفان على الأقل)';
        }
        if (!array_key_exists($facilityType, Facility::getTypes())) {
            $errors[] = 'نوع المرفق غير صالح';
        }
        if (!array_key_exists($location, Facility::getLocations())) {
            $errors[] = 'الموقع غير صالح';
        }

        // Ensure unique code
        $existing = Facility::query()
            ->where('code', '=', $code)
            ->first();
        if ($existing) {
            $code = $code . '_' . bin2hex(random_bytes(2));
        }

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            $session->flash('_old_input', $request->all());
            return $this->redirect('/facilities/create');
        }

        // Build config_json from request
        $config = $this->buildConfigFromRequest($request);

        $facility = Facility::create([
            'code'                    => $code,
            'name_ar'                 => $nameAr,
            'name_en'                 => $nameEn ?: null,
            'facility_type'           => $facilityType,
            'location'                => $location,
            'capacity'                => $capacity,
            'hourly_rate_member'      => $rateM,
            'hourly_rate_nonmember'   => $rateNM,
            'hourly_rate_member_pm'   => $rateMPM,
            'hourly_rate_nonmember_pm'=> $rateNMPM,
            'linked_discipline_id'    => $disciplineId,
            'config_json'             => json_encode($config, JSON_UNESCAPED_UNICODE),
            'is_active'               => 1,
        ]);

        return $this->redirect('/facilities/' . $facility->id)->withSuccess('تم إضافة المرفق بنجاح');
    }

    /**
     * Show facility detail page with time slots and blackout dates.
     */
    public function show(Request $request, string $id): Response
    {
        $facility = Facility::find((int) $id);
        if (!$facility) {
            return $this->redirect('/facilities')->withError('المرفق غير موجود');
        }

        $timeSlots     = FacilityTimeSlot::getForFacility((int) $id);
        $blackoutDates = FacilityBlackoutDate::getForFacility((int) $id);

        // Load linked discipline name if present
        $linkedDiscipline = null;
        if ($facility->linked_discipline_id) {
            $linkedDiscipline = SportDiscipline::find((int) $facility->linked_discipline_id);
        }

        return $this->view('Facilities.Views.show', [
            'facility'          => $facility,
            'config'            => $facility->getConfig(),
            'timeSlots'         => $timeSlots,
            'blackoutDates'     => $blackoutDates,
            'linkedDiscipline'  => $linkedDiscipline,
            'types'             => Facility::getTypes(),
            'locations'         => Facility::getLocations(),
            'slotTypes'         => FacilityTimeSlot::getSlotTypes(),
            'dayLabels'         => FacilityTimeSlot::getDayLabels(),
        ]);
    }

    /**
     * Show edit form for a facility.
     */
    public function edit(Request $request, string $id): Response
    {
        $facility = Facility::find((int) $id);
        if (!$facility) {
            return $this->redirect('/facilities')->withError('المرفق غير موجود');
        }

        return $this->view('Facilities.Views.edit', [
            'facility'    => $facility,
            'config'      => $facility->getConfig(),
            'types'       => Facility::getTypes(),
            'locations'   => Facility::getLocations(),
            'disciplines' => SportDiscipline::allActive(),
        ]);
    }

    /**
     * Validate and update an existing facility.
     */
    public function update(Request $request, string $id): Response
    {
        $facility = Facility::find((int) $id);
        if (!$facility) {
            return $this->redirect('/facilities')->withError('المرفق غير موجود');
        }

        $nameAr       = trim((string) $request->post('name_ar', ''));
        $nameEn       = trim((string) $request->post('name_en', ''));
        $code         = trim((string) $request->post('code', ''));
        $facilityType = trim((string) $request->post('facility_type', ''));
        $location     = trim((string) $request->post('location', ''));
        $capacity     = (int) $request->post('capacity', 0);
        $rateM        = (float) $request->post('hourly_rate_member', 0);
        $rateNM       = (float) $request->post('hourly_rate_nonmember', 0);
        $rateMPM      = (float) $request->post('hourly_rate_member_pm', 0);
        $rateNMPM     = (float) $request->post('hourly_rate_nonmember_pm', 0);
        $disciplineId = $request->post('linked_discipline_id', '');
        $disciplineId = $disciplineId !== '' ? (int) $disciplineId : null;

        // Auto-generate code if empty
        if ($code === '') {
            $typePrefix = strtoupper(substr($facilityType ?: 'FAC', 0, 5));
            $code = $typePrefix . '_' . strtoupper(substr(preg_replace('/[^A-Z0-9]/i', '', $nameEn ?: $nameAr), 0, 10)) . '_' . time() % 10000;
        }
        $code = strtoupper($code);

        // Validation
        $errors = [];
        if ($nameAr === '' || mb_strlen($nameAr) < 2) {
            $errors[] = 'اسم المرفق بالعربي مطلوب (حرفان على الأقل)';
        }
        if (!array_key_exists($facilityType, Facility::getTypes())) {
            $errors[] = 'نوع المرفق غير صالح';
        }
        if (!array_key_exists($location, Facility::getLocations())) {
            $errors[] = 'الموقع غير صالح';
        }

        // Check unique code (exclude current)
        if ($code !== '') {
            $existing = Facility::query()
                ->where('code', '=', $code)
                ->whereRaw('`id` != ?', [(int) $id])
                ->first();
            if ($existing) {
                $errors[] = 'كود المرفق مستخدم بالفعل — جرب كود مختلف';
            }
        }

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            $session->flash('_old_input', $request->all());
            return $this->redirect('/facilities/' . $id . '/edit');
        }

        // Build config_json from request
        $config = $this->buildConfigFromRequest($request);

        $facility->update([
            'code'                    => $code,
            'name_ar'                 => $nameAr,
            'name_en'                 => $nameEn ?: null,
            'facility_type'           => $facilityType,
            'location'                => $location,
            'capacity'                => $capacity,
            'hourly_rate_member'      => $rateM,
            'hourly_rate_nonmember'   => $rateNM,
            'hourly_rate_member_pm'   => $rateMPM,
            'hourly_rate_nonmember_pm'=> $rateNMPM,
            'linked_discipline_id'    => $disciplineId,
            'config_json'             => json_encode($config, JSON_UNESCAPED_UNICODE),
        ]);

        return $this->redirect('/facilities/' . $id)->withSuccess('تم تحديث المرفق بنجاح');
    }

    /**
     * Toggle the is_active status of a facility.
     */
    public function toggle(Request $request, string $id): Response
    {
        $facility = Facility::find((int) $id);
        if (!$facility) {
            return $this->redirect('/facilities')->withError('المرفق غير موجود');
        }

        $newStatus = $facility->is_active ? 0 : 1;
        $facility->update(['is_active' => $newStatus]);

        $message = $newStatus ? 'تم تفعيل المرفق' : 'تم إيقاف المرفق';
        return $this->redirect('/facilities/' . $id)->withSuccess($message);
    }

    /**
     * Add a blackout date for a facility.
     */
    public function addBlackout(Request $request, string $id): Response
    {
        $facility = Facility::find((int) $id);
        if (!$facility) {
            return $this->redirect('/facilities')->withError('المرفق غير موجود');
        }

        $blackoutDate = trim((string) $request->post('blackout_date', ''));
        $startTime    = trim((string) $request->post('start_time', ''));
        $endTime      = trim((string) $request->post('end_time', ''));
        $reason       = trim((string) $request->post('reason', ''));

        $errors = [];
        if ($blackoutDate === '') {
            $errors[] = 'تاريخ الحظر مطلوب';
        }
        if ($reason === '') {
            $errors[] = 'سبب الحظر مطلوب';
        }

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            return $this->redirect('/facilities/' . $id);
        }

        FacilityBlackoutDate::create([
            'facility_id'   => (int) $id,
            'blackout_date' => $blackoutDate,
            'start_time'    => $startTime ?: null,
            'end_time'      => $endTime ?: null,
            'reason'        => $reason,
            'created_by'    => $_SESSION['user_id'] ?? null,
        ]);

        return $this->redirect('/facilities/' . $id)->withSuccess('تم إضافة تاريخ الحظر بنجاح');
    }

    /**
     * Remove a blackout date.
     */
    public function removeBlackout(Request $request, string $id): Response
    {
        $facility = Facility::find((int) $id);
        if (!$facility) {
            return $this->redirect('/facilities')->withError('المرفق غير موجود');
        }

        $blackoutId = (int) $request->post('blackout_id', 0);
        if ($blackoutId > 0) {
            $blackout = FacilityBlackoutDate::find($blackoutId);
            if ($blackout && (int) $blackout->facility_id === (int) $id) {
                $blackout->update(['facility_id' => (int) $id]); // no-op to trigger; use direct delete
                // Direct delete since no soft-delete
                FacilityBlackoutDate::query()
                    ->where('id', '=', $blackoutId)
                    ->where('facility_id', '=', (int) $id)
                    ->first(); // verify ownership
                // Use the model's delete or a raw approach
                $db = App::getInstance()->db();
                $db->execute('DELETE FROM `facility_blackout_dates` WHERE `id` = ? AND `facility_id` = ?', [$blackoutId, (int) $id]);
            }
        }

        return $this->redirect('/facilities/' . $id)->withSuccess('تم حذف تاريخ الحظر');
    }

    public function createTimeSlot(Request $request, string $id): Response
    {
        $facility = Facility::find((int) $id);
        if (!$facility) {
            return $this->redirect('/facilities')->withError('المرفق غير موجود');
        }

        $db = App::getInstance()->db();
        $units = $db->select("SELECT id, name_ar FROM facility_units WHERE facility_id = ? AND is_active = 1 ORDER BY name_ar", [(int) $id]);

        return $this->view('Facilities.Views.timeslots.create', [
            'facility' => $facility,
            'units'    => $units,
        ]);
    }

    public function storeTimeSlot(Request $request, string $id): Response
    {
        $facility = Facility::find((int) $id);
        if (!$facility) {
            return $this->redirect('/facilities')->withError('المرفق غير موجود');
        }

        $db = App::getInstance()->db();
        $unitId = (int) $request->post('facility_unit_id', 0);
        $dayOfWeek = (int) $request->post('day_of_week', 0);
        $startTime = trim((string) $request->post('start_time', ''));
        $endTime = trim((string) $request->post('end_time', ''));
        $slotType = trim((string) $request->post('slot_type', 'blocked'));
        $label = trim((string) $request->post('label', ''));

        if ($startTime === '' || $endTime === '') {
            return $this->redirect("/facilities/{$id}/timeslots/create")->withError('وقت البداية والنهاية مطلوبان');
        }

        $db->insert('facility_time_slots', [
            'facility_id'      => (int) $id,
            'facility_unit_id' => $unitId > 0 ? $unitId : null,
            'day_of_week'      => $dayOfWeek,
            'start_time'       => $startTime,
            'end_time'         => $endTime,
            'slot_type'        => $slotType,
            'label'            => $label ?: null,
            'is_active'        => 1,
            'created_at'       => date('Y-m-d H:i:s'),
            'updated_at'       => date('Y-m-d H:i:s'),
        ]);

        return $this->redirect('/facilities/' . $id)->withSuccess('تم حظر الفترة الزمنية بنجاح');
    }

    public function deleteTimeSlot(Request $request, string $id, string $slotId): Response
    {
        $db = App::getInstance()->db();
        $db->delete('facility_time_slots', 'id = ? AND facility_id = ?', [(int) $slotId, (int) $id]);
        return $this->redirect('/facilities/' . $id)->withSuccess('تم حذف الفترة الزمنية');
    }

    /**
     * Build the config array from the request.
     */
    private function buildConfigFromRequest(Request $request): array
    {
        $config = [];

        // Surface type (e.g., grass, artificial, wood, etc.)
        $surfaceType = trim((string) $request->post('surface_type', ''));
        if ($surfaceType !== '') {
            $config['surface_type'] = $surfaceType;
        }

        // Lighting availability
        $hasLighting = $request->post('has_lighting');
        if ($hasLighting) {
            $config['has_lighting'] = true;
        }

        // Changing rooms
        $hasChangingRooms = $request->post('has_changing_rooms');
        if ($hasChangingRooms) {
            $config['has_changing_rooms'] = true;
        }

        // Dimensions
        $dimensions = trim((string) $request->post('dimensions', ''));
        if ($dimensions !== '') {
            $config['dimensions'] = $dimensions;
        }

        // Notes
        $notes = trim((string) $request->post('config_notes', ''));
        if ($notes !== '') {
            $config['notes'] = $notes;
        }

        return $config;
    }
}
