<?php
declare(strict_types=1);

namespace App\Modules\FacilityGrids\Services;

use App\Core\App;
use App\Core\EventBus;

final class FacilityAttendanceService
{
    private \App\Core\Database $db;

    public function __construct()
    {
        $this->db = App::getInstance()->db();
    }

    public function recordBatch(int $gridId, string $date, ?string $hourSlot, array $records, ?int $recordedBy = null): int
    {
        $count = 0;
        foreach ($records as $record) {
            $existing = $this->db->selectOne(
                "SELECT id FROM facility_attendance
                 WHERE grid_id = ? AND attendance_date = ? AND entity_type = ? AND entity_id = ?
                 AND (hour_slot = ? OR (hour_slot IS NULL AND ? IS NULL))",
                [$gridId, $date, $record['entity_type'], (int) $record['entity_id'], $hourSlot, $hourSlot]
            );

            if ($existing) {
                $this->db->update('facility_attendance', [
                    'status' => $record['status'],
                    'check_in_time' => $record['check_in_time'] ?? null,
                    'notes' => $record['notes'] ?? null,
                ], 'id = ?', [(int) $existing['id']]);
            } else {
                $this->db->insert('facility_attendance', [
                    'grid_id' => $gridId,
                    'attendance_date' => $date,
                    'hour_slot' => $hourSlot,
                    'entity_type' => $record['entity_type'],
                    'entity_id' => (int) $record['entity_id'],
                    'entity_name_cache' => $record['entity_name'] ?? null,
                    'status' => $record['status'],
                    'check_in_time' => $record['check_in_time'] ?? null,
                    'notes' => $record['notes'] ?? null,
                    'recorded_by' => $recordedBy,
                ]);
            }
            $count++;

            if ($record['status'] === 'absent') {
                EventBus::dispatch('facility.attendance_absent', [
                    'entity_type' => $record['entity_type'],
                    'entity_id' => (int) $record['entity_id'],
                    'grid_id' => $gridId,
                    'date' => $date,
                ]);
            }
        }

        return $count;
    }

    public function getForGrid(int $gridId, string $date, ?string $hourSlot = null): array
    {
        $where = 'grid_id = ? AND attendance_date = ?';
        $params = [$gridId, $date];

        if ($hourSlot !== null) {
            $where .= ' AND hour_slot = ?';
            $params[] = $hourSlot;
        }

        return $this->db->select(
            "SELECT * FROM facility_attendance WHERE {$where} ORDER BY entity_type, entity_name_cache",
            $params
        );
    }

    public function getReport(int $gridId, string $dateFrom, string $dateTo): array
    {
        $summary = $this->db->select(
            "SELECT entity_type, entity_id, entity_name_cache,
                    COUNT(*) as total_days,
                    SUM(CASE WHEN status = 'present' THEN 1 ELSE 0 END) as present_count,
                    SUM(CASE WHEN status = 'absent' THEN 1 ELSE 0 END) as absent_count,
                    SUM(CASE WHEN status = 'late' THEN 1 ELSE 0 END) as late_count,
                    SUM(CASE WHEN status = 'excused' THEN 1 ELSE 0 END) as excused_count
             FROM facility_attendance
             WHERE grid_id = ? AND attendance_date BETWEEN ? AND ?
             GROUP BY entity_type, entity_id, entity_name_cache
             ORDER BY entity_type, entity_name_cache",
            [$gridId, $dateFrom, $dateTo]
        );

        return $summary;
    }

    public function sendPaymentReminders(int $gridId): int
    {
        $trainees = $this->db->select(
            "SELECT DISTINCT fzt.player_id, p.name_ar, p.phone
             FROM facility_zone_trainees fzt
             INNER JOIN facility_grid_zones fgz ON fgz.id = fzt.zone_id
             INNER JOIN players p ON p.id = fzt.player_id
             WHERE fgz.grid_id = ? AND fzt.is_active = 1",
            [$gridId]
        );

        $count = 0;
        foreach ($trainees as $trainee) {
            EventBus::dispatch('facility.payment_reminder', [
                'player_id' => (int) $trainee['player_id'],
                'player_name' => $trainee['name_ar'],
                'phone' => $trainee['phone'],
                'grid_id' => $gridId,
            ]);
            $count++;
        }

        return $count;
    }
}
