<?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\Modules\SportsActivity\Services\ScheduleGeneratorService;
use App\Modules\SportsActivity\Services\ScheduleCopyService;

class ScheduleController extends Controller
{
    /**
     * Redirect to daily view with today's date.
     */
    public function calendar(Request $request): Response
    {
        return $this->redirect('/sa/schedule/daily/' . date('Y-m-d'));
    }

    /**
     * Show all bookings for a given date across all facilities.
     */
    public function daily(Request $request, string $date): Response
    {
        $db = App::getInstance()->db();

        // Validate date format
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
            $date = date('Y-m-d');
        }

        $bookings = $db->select(
            "SELECT b.*, fu.name_ar as unit_name, fu.code as unit_code,
                    f.name_ar as facility_name, f.id as facility_id,
                    g.name_ar as group_name, c.full_name_ar as coach_name
             FROM sa_bookings b
             JOIN sa_facility_units fu ON fu.id = b.facility_unit_id
             JOIN sa_facilities f ON f.id = fu.facility_id
             LEFT JOIN sa_groups g ON g.id = b.group_id
             LEFT JOIN sa_coaches c ON c.id = b.coach_id
             WHERE b.booking_date = ? AND b.status != 'cancelled'
             ORDER BY f.name_ar ASC, fu.name_ar ASC, b.start_time ASC",
            [$date]
        );

        // Group bookings by facility -> unit
        $byFacility = [];
        foreach ($bookings as $b) {
            $key = $b['facility_name'];
            if (!isset($byFacility[$key])) {
                $byFacility[$key] = [];
            }
            $unitKey = $b['unit_name'] . ' (' . $b['unit_code'] . ')';
            if (!isset($byFacility[$key][$unitKey])) {
                $byFacility[$key][$unitKey] = [];
            }
            $byFacility[$key][$unitKey][] = $b;
        }

        // Get all active facility units for the full grid
        $allUnits = $db->select(
            "SELECT fu.id, fu.name_ar, fu.code, f.name_ar as facility_name
             FROM sa_facility_units fu
             JOIN sa_facilities f ON f.id = fu.facility_id
             WHERE fu.is_active = 1
             ORDER BY f.name_ar ASC, fu.name_ar ASC",
            []
        );

        // Groups for the generate form
        $groups = $db->select(
            "SELECT g.id, g.name_ar, g.code FROM sa_groups g WHERE g.status = 'active' AND g.is_archived = 0 ORDER BY g.name_ar",
            []
        );

        return $this->view('SportsActivity.Views.schedule.daily', [
            'date'       => $date,
            'byFacility' => $byFacility,
            'allUnits'   => $allUnits,
            'groups'     => $groups,
        ]);
    }

    /**
     * Show current week schedule as grid (facilities x days).
     */
    public function weekly(Request $request): Response
    {
        $db = App::getInstance()->db();

        // Determine week start (Saturday) and end (Friday) for Arabic week
        $weekStart = trim((string) $request->get('week_start', ''));
        if ($weekStart === '' || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $weekStart)) {
            // Find last Saturday
            $now = new \DateTime();
            $dayOfWeek = (int) $now->format('w'); // 0=Sun, 6=Sat
            $diff = ($dayOfWeek + 1) % 7; // days since Saturday
            $now->modify("-{$diff} days");
            $weekStart = $now->format('Y-m-d');
        }

        $startDate = new \DateTime($weekStart);
        $endDate = (clone $startDate)->modify('+6 days');

        $days = [];
        $dayNames = ['السبت', 'الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة'];
        $current = clone $startDate;
        for ($i = 0; $i < 7; $i++) {
            $days[] = [
                'date' => $current->format('Y-m-d'),
                'name' => $dayNames[$i],
                'day'  => $current->format('d'),
            ];
            $current->modify('+1 day');
        }

        // Get facility units
        $units = $db->select(
            "SELECT fu.id, fu.name_ar, fu.code, f.name_ar as facility_name
             FROM sa_facility_units fu
             JOIN sa_facilities f ON f.id = fu.facility_id
             WHERE fu.is_active = 1
             ORDER BY f.name_ar ASC, fu.name_ar ASC",
            []
        );

        // Get booking counts per unit per day
        $counts = $db->select(
            "SELECT facility_unit_id, booking_date, COUNT(*) as cnt
             FROM sa_bookings
             WHERE booking_date BETWEEN ? AND ? AND status != 'cancelled'
             GROUP BY facility_unit_id, booking_date",
            [$startDate->format('Y-m-d'), $endDate->format('Y-m-d')]
        );

        // Build lookup: unit_id -> date -> count
        $countMap = [];
        foreach ($counts as $row) {
            $countMap[(int) $row['facility_unit_id']][$row['booking_date']] = (int) $row['cnt'];
        }

        return $this->view('SportsActivity.Views.schedule.weekly', [
            'days'      => $days,
            'units'     => $units,
            'countMap'  => $countMap,
            'weekStart' => $startDate->format('Y-m-d'),
            'prevWeek'  => (clone $startDate)->modify('-7 days')->format('Y-m-d'),
            'nextWeek'  => (clone $startDate)->modify('+7 days')->format('Y-m-d'),
        ]);
    }

    /**
     * Generate training bookings for a group + date range.
     */
    public function generate(Request $request): Response
    {
        $groupId = (int) $request->post('group_id', 0);
        $fromDate = trim((string) $request->post('from_date', ''));
        $toDate = trim((string) $request->post('to_date', ''));

        $errors = [];
        if ($groupId === 0) {
            $errors[] = 'يرجى اختيار المجموعة';
        }
        if ($fromDate === '') {
            $errors[] = 'تاريخ البداية مطلوب';
        }
        if ($toDate === '') {
            $errors[] = 'تاريخ النهاية مطلوب';
        }

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            return $this->redirect('/sa/schedule/daily/' . ($fromDate ?: date('Y-m-d')));
        }

        $result = ScheduleGeneratorService::generateForGroup($groupId, $fromDate, $toDate);

        if ($result['success']) {
            $msg = "تم توليد {$result['generated']} حجز تدريبي";
            if ($result['skipped'] > 0) {
                $msg .= " (تم تخطي {$result['skipped']})";
            }
            return $this->redirect('/sa/schedule/daily/' . $fromDate)->withSuccess($msg);
        }

        return $this->redirect('/sa/schedule/daily/' . ($fromDate ?: date('Y-m-d')))->withError($result['error']);
    }

    public function copySchedule(Request $request): Response
    {
        $sourceGroupId = (int) $request->post('source_group_id', 0);
        $targetGroupId = (int) $request->post('target_group_id', 0);

        if (!$sourceGroupId || !$targetGroupId) {
            return $this->redirect('/sa/schedule')->withError('يجب اختيار المجموعة المصدر والمستهدفة');
        }

        $result = ScheduleCopyService::copyGroupSchedule($sourceGroupId, $targetGroupId);

        if (!$result['success']) {
            return $this->redirect('/sa/schedule')->withError($result['error']);
        }

        return $this->redirect('/sa/schedule')
            ->withSuccess("تم نسخ {$result['copied']} حصة من الجدول بنجاح");
    }

    public function shiftTime(Request $request): Response
    {
        $groupId = (int) $request->post('group_id', 0);
        $minutes = (int) $request->post('minutes_delta', 0);

        if (!$groupId || !$minutes) {
            return $this->redirect('/sa/schedule')->withError('يجب تحديد المجموعة وعدد الدقائق');
        }

        $result = ScheduleCopyService::shiftScheduleTime($groupId, $minutes);

        if (!$result['success']) {
            return $this->redirect('/sa/schedule')->withError($result['error']);
        }

        $direction = $minutes > 0 ? 'تقديم' : 'تأخير';
        return $this->redirect('/sa/schedule')
            ->withSuccess("تم {$direction} مواعيد المجموعة بـ " . abs($minutes) . " دقيقة");
    }
}
