<?php
declare(strict_types=1);

namespace App\Modules\PlayerAffairs\Services;

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

class MedicalScanService
{
    private const UPLOAD_DIR = 'uploads/medical_scans';
    private const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];
    private const MAX_SIZE = 5 * 1024 * 1024; // 5MB

    public static function uploadScan(array $file, int $playerId, int $recordId): string
    {
        if (empty($file['tmp_name']) || $file['error'] !== UPLOAD_ERR_OK) {
            throw new \RuntimeException('خطأ في رفع الملف', 400);
        }

        if ($file['size'] > self::MAX_SIZE) {
            throw new \RuntimeException('حجم الملف يتجاوز 5 ميجابايت', 400);
        }

        $mimeType = mime_content_type($file['tmp_name']);
        if (!in_array($mimeType, self::ALLOWED_TYPES, true)) {
            throw new \RuntimeException('نوع الملف غير مدعوم. الأنواع المسموحة: JPG, PNG, WebP, PDF', 400);
        }

        $uploadDir = rtrim($_SERVER['DOCUMENT_ROOT'] ?? 'public', '/') . '/' . self::UPLOAD_DIR;
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }

        $extension = match ($mimeType) {
            'image/jpeg' => 'jpg',
            'image/png'  => 'png',
            'image/webp' => 'webp',
            'application/pdf' => 'pdf',
            default => 'bin',
        };

        $filename = sprintf('med_%d_%d_%s.%s', $playerId, $recordId, date('Ymd_His'), $extension);
        $filepath = $uploadDir . '/' . $filename;

        if (!move_uploaded_file($file['tmp_name'], $filepath)) {
            throw new \RuntimeException('فشل في حفظ الملف', 500);
        }

        $relativePath = self::UPLOAD_DIR . '/' . $filename;

        $db = App::getInstance()->db();
        $db->insert('documents', [
            'entity_type'   => 'medical_record',
            'entity_id'     => $recordId,
            'document_type' => 'medical_scan',
            'file_path'     => $relativePath,
            'file_name'     => $file['name'],
            'file_size'     => $file['size'],
            'mime_type'     => $mimeType,
            'uploaded_by'   => (int) ($_SESSION['employee_id'] ?? 0),
            'created_at'    => date('Y-m-d H:i:s'),
            'updated_at'    => date('Y-m-d H:i:s'),
        ]);

        $documentId = (int) $db->selectOne("SELECT LAST_INSERT_ID() AS id")['id'];

        $db->update('player_medical_records', [
            'document_id' => $documentId,
            'updated_at'  => date('Y-m-d H:i:s'),
        ], '`id` = ?', [$recordId]);

        return $relativePath;
    }

    public static function getExpiringRecords(int $daysAhead = 30): array
    {
        $db = App::getInstance()->db();
        $futureDate = date('Y-m-d', strtotime("+{$daysAhead} days"));

        return $db->select(
            "SELECT pmr.*, p.full_name_ar AS player_name, p.id AS player_id
             FROM player_medical_records pmr
             LEFT JOIN players p ON p.id = pmr.player_id
             WHERE pmr.expiry_date IS NOT NULL
             AND pmr.expiry_date <= ?
             AND pmr.expiry_date >= CURDATE()
             AND pmr.approval_status = 'approved'
             ORDER BY pmr.expiry_date ASC",
            [$futureDate]
        );
    }

    public static function getExpiredRecords(): array
    {
        $db = App::getInstance()->db();
        return $db->select(
            "SELECT pmr.*, p.full_name_ar AS player_name, p.id AS player_id
             FROM player_medical_records pmr
             LEFT JOIN players p ON p.id = pmr.player_id
             WHERE pmr.expiry_date IS NOT NULL
             AND pmr.expiry_date < CURDATE()
             AND pmr.approval_status = 'approved'
             ORDER BY pmr.expiry_date DESC"
        );
    }

    public static function checkExpiryAndNotify(): int
    {
        $expiring = self::getExpiringRecords(14);
        $notified = 0;

        foreach ($expiring as $record) {
            $daysLeft = (int) ((strtotime($record['expiry_date']) - time()) / 86400);
            if ($daysLeft <= 14 && $daysLeft > 0) {
                EventBus::dispatch('medical.expiring_soon', [
                    'player_id'   => (int) $record['player_id'],
                    'record_id'   => (int) $record['id'],
                    'expiry_date' => $record['expiry_date'],
                    'days_left'   => $daysLeft,
                    'record_type' => $record['record_type'],
                ]);
                $notified++;
            }
        }

        $expired = self::getExpiredRecords();
        foreach ($expired as $record) {
            EventBus::dispatch('medical.expired', [
                'player_id'   => (int) $record['player_id'],
                'record_id'   => (int) $record['id'],
                'expiry_date' => $record['expiry_date'],
                'record_type' => $record['record_type'],
            ]);
        }

        return $notified;
    }
}
