<?php
declare(strict_types=1);

namespace App\Modules\SportsActivity\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\Pagination;
use App\Modules\SportsActivity\Models\Facility;
use App\Modules\SportsActivity\Models\FacilityUnit;
use App\Modules\SportsActivity\Models\TimeBracket;
use App\Modules\SportsActivity\Models\Discipline;

class FacilityController extends Controller
{
    public function index(Request $request): Response
    {
        $this->authorize('sa.facility.view');

        $db = App::getInstance()->db();
        $search = trim((string) $request->get('q', ''));
        $typeFilter = trim((string) $request->get('type', ''));
        $page = max(1, (int) $request->get('page', 1));
        $perPage = 25;

        $where = ['f.is_archived = 0'];
        $params = [];

        if ($search !== '') {
            $where[] = "(f.name_ar LIKE ? OR f.name_en LIKE ? OR f.code LIKE ?)";
            $params[] = "%{$search}%";
            $params[] = "%{$search}%";
            $params[] = "%{$search}%";
        }

        if ($typeFilter !== '') {
            $where[] = "f.facility_type = ?";
            $params[] = $typeFilter;
        }

        $whereSql = implode(' AND ', $where);

        $total = (int) $db->selectOne(
            "SELECT COUNT(*) as cnt FROM sa_facilities f WHERE {$whereSql}",
            $params
        )['cnt'];

        $pagination = Pagination::paginate($total, $perPage, $page);
        $offset = ($pagination['current_page'] - 1) * $perPage;

        $rows = $db->select(
            "SELECT f.*, d.name_ar as discipline_name,
                    (SELECT COUNT(*) FROM sa_facility_units u WHERE u.facility_id = f.id AND u.is_active = 1) as unit_count
             FROM sa_facilities f
             LEFT JOIN sa_disciplines d ON d.id = f.discipline_id
             WHERE {$whereSql}
             ORDER BY f.name_ar ASC
             LIMIT {$perPage} OFFSET {$offset}",
            $params
        );

        return $this->view('SportsActivity.Views.facilities.index', [
            'rows'        => $rows,
            'pagination'  => $pagination,
            'filters'     => ['q' => $search, 'type' => $typeFilter],
            'typeOptions' => Facility::getTypeOptions(),
        ]);
    }

    public function create(Request $request): Response
    {
        $this->authorize('sa.facility.manage');

        return $this->view('SportsActivity.Views.facilities.create', [
            'typeOptions'  => Facility::getTypeOptions(),
            'disciplines'  => Discipline::getActive(),
        ]);
    }

    public function store(Request $request): Response
    {
        $this->authorize('sa.facility.manage');

        $code = trim((string) $request->post('code', ''));
        $nameAr = trim((string) $request->post('name_ar', ''));
        $nameEn = trim((string) $request->post('name_en', ''));
        $facilityType = trim((string) $request->post('facility_type', ''));
        $disciplineId = $request->post('discipline_id', '');
        $location = trim((string) $request->post('location_description', ''));
        $opStart = trim((string) $request->post('operating_start', ''));
        $opEnd = trim((string) $request->post('operating_end', ''));
        $slotMinutes = (int) $request->post('slot_minutes', 60);

        // Validation
        $errors = [];
        if ($code === '') {
            $errors[] = 'الكود مطلوب';
        } elseif (mb_strlen($code) > 30) {
            $errors[] = 'الكود يجب ألا يتجاوز 30 حرف';
        }
        if ($nameAr === '') {
            $errors[] = 'الاسم بالعربية مطلوب';
        } elseif (mb_strlen($nameAr) > 300) {
            $errors[] = 'الاسم بالعربية يجب ألا يتجاوز 300 حرف';
        }
        if ($nameEn !== '' && mb_strlen($nameEn) > 300) {
            $errors[] = 'الاسم بالإنجليزية يجب ألا يتجاوز 300 حرف';
        }
        if ($facilityType === '' || !isset(Facility::getTypeOptions()[$facilityType])) {
            $errors[] = 'نوع المنشأة مطلوب';
        }
        if ($location !== '' && mb_strlen($location) > 500) {
            $errors[] = 'وصف الموقع يجب ألا يتجاوز 500 حرف';
        }
        if ($opStart === '' || $opEnd === '') {
            $errors[] = 'ساعات التشغيل مطلوبة';
        } elseif ($opStart >= $opEnd) {
            $errors[] = 'وقت البدء يجب أن يكون قبل وقت الانتهاء';
        }
        if ($slotMinutes < 15 || $slotMinutes > 240) {
            $errors[] = 'مدة الفترة يجب أن تكون بين 15 و 240 دقيقة';
        }

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

        // Check duplicate code
        $db = App::getInstance()->db();
        $existing = $db->selectOne("SELECT id FROM sa_facilities WHERE code = ? AND is_archived = 0", [$code]);
        if ($existing) {
            $session = App::getInstance()->session();
            $session->flash('_old_input', $_POST);
            $session->flash('_alerts', [['type' => 'error', 'message' => 'الكود مستخدم بالفعل']]);
            return $this->redirect('/sa/facilities/create');
        }

        $operatingHoursJson = json_encode([
            'start'        => $opStart,
            'end'          => $opEnd,
            'slot_minutes' => $slotMinutes,
        ], JSON_UNESCAPED_UNICODE);

        Facility::create([
            'code'                 => $code,
            'name_ar'              => $nameAr,
            'name_en'              => $nameEn ?: null,
            'facility_type'        => $facilityType,
            'discipline_id'        => $disciplineId !== '' ? (int) $disciplineId : null,
            'location_description' => $location ?: null,
            'operating_hours_json' => $operatingHoursJson,
            'is_active'            => 1,
            'branch_id'            => null,
        ]);

        return $this->redirect('/sa/facilities')->withSuccess('تم إضافة المنشأة بنجاح');
    }

    public function show(Request $request, string $id): Response
    {
        $this->authorize('sa.facility.view');

        $facility = Facility::find((int) $id);
        if (!$facility) {
            return $this->redirect('/sa/facilities')->withError('المنشأة غير موجودة');
        }

        $units = FacilityUnit::getByFacility((int) $id);
        $brackets = TimeBracket::getByFacility((int) $id);

        $db = App::getInstance()->db();
        $discipline = null;
        if ($facility->discipline_id) {
            $discipline = $db->selectOne("SELECT * FROM sa_disciplines WHERE id = ?", [(int) $facility->discipline_id]);
        }

        $trainingGroups = $db->select(
            "SELECT DISTINCT g.id, g.name_ar, g.code, c.full_name_ar as coach_name,
                    GROUP_CONCAT(DISTINCT CONCAT(gs.day_of_week, '|', gs.start_time, '-', gs.end_time) SEPARATOR ',') as schedule_info
             FROM sa_group_schedule gs
             INNER JOIN sa_groups g ON g.id = gs.group_id AND g.status = 'active' AND g.is_archived = 0
             LEFT JOIN sa_coaches c ON c.id = g.coach_id
             WHERE gs.facility_unit_id IN (SELECT id FROM sa_facility_units WHERE facility_id = ?)
             AND gs.is_active = 1
             GROUP BY g.id, g.name_ar, g.code, c.full_name_ar
             ORDER BY g.name_ar ASC",
            [(int) $id]
        );

        return $this->view('SportsActivity.Views.facilities.show', [
            'facility'        => $facility,
            'units'           => $units,
            'brackets'        => $brackets,
            'discipline'      => $discipline,
            'trainingGroups'  => $trainingGroups,
            'typeOptions'     => Facility::getTypeOptions(),
            'bracketTypes'    => TimeBracket::getBracketTypeOptions(),
            'unitTypeOptions' => FacilityUnit::getUnitTypeOptions(),
            'bookingModes'    => FacilityUnit::getBookingModeOptions(),
        ]);
    }

    public function edit(Request $request, string $id): Response
    {
        $this->authorize('sa.facility.manage');

        $facility = Facility::find((int) $id);
        if (!$facility) {
            return $this->redirect('/sa/facilities')->withError('المنشأة غير موجودة');
        }

        return $this->view('SportsActivity.Views.facilities.edit', [
            'facility'     => $facility,
            'typeOptions'  => Facility::getTypeOptions(),
            'disciplines'  => Discipline::getActive(),
        ]);
    }

    public function update(Request $request, string $id): Response
    {
        $this->authorize('sa.facility.manage');

        $facility = Facility::find((int) $id);
        if (!$facility) {
            return $this->redirect('/sa/facilities')->withError('المنشأة غير موجودة');
        }

        $code = trim((string) $request->post('code', ''));
        $nameAr = trim((string) $request->post('name_ar', ''));
        $nameEn = trim((string) $request->post('name_en', ''));
        $facilityType = trim((string) $request->post('facility_type', ''));
        $disciplineId = $request->post('discipline_id', '');
        $location = trim((string) $request->post('location_description', ''));
        $opStart = trim((string) $request->post('operating_start', ''));
        $opEnd = trim((string) $request->post('operating_end', ''));
        $slotMinutes = (int) $request->post('slot_minutes', 60);

        // Validation
        $errors = [];
        if ($code === '') {
            $errors[] = 'الكود مطلوب';
        } elseif (mb_strlen($code) > 30) {
            $errors[] = 'الكود يجب ألا يتجاوز 30 حرف';
        }
        if ($nameAr === '') {
            $errors[] = 'الاسم بالعربية مطلوب';
        } elseif (mb_strlen($nameAr) > 300) {
            $errors[] = 'الاسم بالعربية يجب ألا يتجاوز 300 حرف';
        }
        if ($nameEn !== '' && mb_strlen($nameEn) > 300) {
            $errors[] = 'الاسم بالإنجليزية يجب ألا يتجاوز 300 حرف';
        }
        if ($facilityType === '' || !isset(Facility::getTypeOptions()[$facilityType])) {
            $errors[] = 'نوع المنشأة مطلوب';
        }
        if ($location !== '' && mb_strlen($location) > 500) {
            $errors[] = 'وصف الموقع يجب ألا يتجاوز 500 حرف';
        }
        if ($opStart === '' || $opEnd === '') {
            $errors[] = 'ساعات التشغيل مطلوبة';
        } elseif ($opStart >= $opEnd) {
            $errors[] = 'وقت البدء يجب أن يكون قبل وقت الانتهاء';
        }
        if ($slotMinutes < 15 || $slotMinutes > 240) {
            $errors[] = 'مدة الفترة يجب أن تكون بين 15 و 240 دقيقة';
        }

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

        // Check duplicate code (excluding current)
        $db = App::getInstance()->db();
        $existing = $db->selectOne(
            "SELECT id FROM sa_facilities WHERE code = ? AND is_archived = 0 AND id != ?",
            [$code, (int) $id]
        );
        if ($existing) {
            $session = App::getInstance()->session();
            $session->flash('_old_input', $_POST);
            $session->flash('_alerts', [['type' => 'error', 'message' => 'الكود مستخدم بالفعل']]);
            return $this->redirect("/sa/facilities/{$id}/edit");
        }

        $operatingHoursJson = json_encode([
            'start'        => $opStart,
            'end'          => $opEnd,
            'slot_minutes' => $slotMinutes,
        ], JSON_UNESCAPED_UNICODE);

        $facility->update([
            'code'                 => $code,
            'name_ar'              => $nameAr,
            'name_en'              => $nameEn ?: null,
            'facility_type'        => $facilityType,
            'discipline_id'        => $disciplineId !== '' ? (int) $disciplineId : null,
            'location_description' => $location ?: null,
            'operating_hours_json' => $operatingHoursJson,
        ]);

        return $this->redirect("/sa/facilities/{$id}")->withSuccess('تم تحديث المنشأة بنجاح');
    }

    public function toggle(Request $request, string $id): Response
    {
        $this->authorize('sa.facility.manage');

        $facility = Facility::find((int) $id);
        if (!$facility) {
            return $this->redirect('/sa/facilities')->withError('المنشأة غير موجودة');
        }

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

        $msg = $newStatus ? 'تم تفعيل المنشأة' : 'تم تعطيل المنشأة';
        return $this->redirect('/sa/facilities')->withSuccess($msg);
    }

    public function brackets(Request $request, string $fid): Response
    {
        $this->authorize('sa.facility.view');

        $facility = Facility::find((int) $fid);
        if (!$facility) {
            return $this->redirect('/sa/facilities')->withError('المنشأة غير موجودة');
        }

        $brackets = TimeBracket::getByFacility((int) $fid);

        return $this->view('SportsActivity.Views.facilities.time_brackets', [
            'facility'     => $facility,
            'brackets'     => $brackets,
            'bracketTypes' => TimeBracket::getBracketTypeOptions(),
        ]);
    }

    public function storeBracket(Request $request, string $fid): Response
    {
        $this->authorize('sa.facility.manage');

        $facility = Facility::find((int) $fid);
        if (!$facility) {
            return $this->redirect('/sa/facilities')->withError('المنشأة غير موجودة');
        }

        $nameAr = trim((string) $request->post('name_ar', ''));
        $bracketType = trim((string) $request->post('bracket_type', ''));
        $startTime = trim((string) $request->post('start_time', ''));
        $endTime = trim((string) $request->post('end_time', ''));
        $daysOfWeek = $request->post('days_of_week', []);

        // Validation
        $errors = [];
        if ($nameAr === '') {
            $errors[] = 'اسم الفترة مطلوب';
        } elseif (mb_strlen($nameAr) > 100) {
            $errors[] = 'اسم الفترة يجب ألا يتجاوز 100 حرف';
        }
        if ($bracketType === '' || !isset(TimeBracket::getBracketTypeOptions()[$bracketType])) {
            $errors[] = 'نوع الفترة مطلوب';
        }
        if ($startTime === '' || $endTime === '') {
            $errors[] = 'وقت البداية والنهاية مطلوبان';
        } elseif ($startTime >= $endTime) {
            $errors[] = 'وقت البدء يجب أن يكون قبل وقت الانتهاء';
        }
        if (empty($daysOfWeek) || !is_array($daysOfWeek)) {
            $errors[] = 'يجب اختيار يوم واحد على الأقل';
        }

        if (empty($errors) && !empty($daysOfWeek) && $startTime !== '' && $endTime !== '') {
            $db = App::getInstance()->db();
            $existing = $db->select(
                "SELECT id, name_ar, start_time, end_time, days_of_week_json
                 FROM sa_time_brackets
                 WHERE facility_id = ? AND is_active = 1",
                [(int) $fid]
            );
            $newDays = array_map('intval', (array) $daysOfWeek);
            foreach ($existing as $bracket) {
                $existingDays = json_decode($bracket['days_of_week_json'], true) ?: [];
                $sharedDays = array_intersect($newDays, $existingDays);
                if (!empty($sharedDays) && $startTime < $bracket['end_time'] && $endTime > $bracket['start_time']) {
                    $errors[] = "تتعارض هذه الفترة مع فترة \"{$bracket['name_ar']}\" في نفس الأيام والأوقات";
                    break;
                }
            }
        }

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_old_input', $_POST);
            $alerts = array_map(fn($msg) => ['type' => 'error', 'message' => $msg], $errors);
            $session->flash('_alerts', $alerts);
            return $this->redirect("/sa/facilities/{$fid}/brackets");
        }

        $daysJson = json_encode(array_map('intval', (array) $daysOfWeek));

        TimeBracket::create([
            'facility_id'      => (int) $fid,
            'name_ar'          => $nameAr,
            'name_en'          => null,
            'bracket_type'     => $bracketType,
            'start_time'       => $startTime,
            'end_time'         => $endTime,
            'days_of_week_json' => $daysJson,
            'is_active'        => 1,
        ]);

        return $this->redirect("/sa/facilities/{$fid}/brackets")->withSuccess('تم إضافة الفترة الزمنية بنجاح');
    }

    public function deleteBracket(Request $request, string $fid, string $id): Response
    {
        $this->authorize('sa.facility.manage');

        $facility = Facility::find((int) $fid);
        if (!$facility) {
            return $this->redirect('/sa/facilities')->withError('المنشأة غير موجودة');
        }

        $bracket = TimeBracket::find((int) $id);
        if (!$bracket || (int) $bracket->facility_id !== (int) $fid) {
            return $this->redirect("/sa/facilities/{$fid}/brackets")->withError('الفترة الزمنية غير موجودة');
        }

        $bracket->update(['is_active' => 0]);

        return $this->redirect("/sa/facilities/{$fid}/brackets")->withSuccess('تم حذف الفترة الزمنية');
    }

    public function addBlackout(Request $request, string $id): Response
    {
        $this->authorize('sa.facility.manage');

        $facility = Facility::find((int) $id);
        if (!$facility) {
            return $this->redirect('/sa/facilities')->withError('المنشأة غير موجودة');
        }

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

        if ($blackoutDate === '') {
            return $this->redirect("/sa/facilities/{$id}")->withError('تاريخ الإيقاف مطلوب');
        }

        $db = App::getInstance()->db();
        $db->insert('sa_blackout_dates', [
            'facility_id'   => (int) $id,
            'blackout_date' => $blackoutDate,
            'reason'        => $reason ?: null,
            'created_at'    => date('Y-m-d H:i:s'),
        ]);

        return $this->redirect("/sa/facilities/{$id}")->withSuccess('تم إضافة تاريخ الإيقاف');
    }
}
