<?php

/**
 * Validadores de Datos del Paciente
 * Valida información para agendamientos y procesos
 */

class PatientDataValidator
{
    /**
     * Valida todos los datos del paciente para agendamiento
     * @param array $data
     * @return array ['valid' => bool, 'errors' => array, 'data' => array]
     */
    public static function validateAppointmentData(array $data): array
    {
        $errors = [];
        $validData = [];
        
        // Nombre completo
        if (empty($data['nombre'])) {
            $errors[] = "Falta el nombre completo";
        } elseif (!self::validateFullName($data['nombre'])) {
            $errors[] = "El nombre debe tener al menos nombre y apellido";
        } else {
            $validData['nombre'] = self::sanitizeName($data['nombre']);
        }
        
        // Documento
        if (empty($data['documento'])) {
            $errors[] = "Falta el número de documento";
        } elseif (!self::validateDocument($data['documento'])) {
            $errors[] = "El documento debe tener entre 6 y 11 dígitos";
        } else {
            $validData['documento'] = self::sanitizeDocument($data['documento']);
        }
        
        // Dirección
        if (empty($data['direccion'])) {
            $errors[] = "Falta la dirección completa";
        } elseif (strlen($data['direccion']) < 10) {
            $errors[] = "La dirección debe ser más específica (mínimo 10 caracteres)";
        } else {
            $validData['direccion'] = trim($data['direccion']);
        }
        
        // Teléfono
        if (empty($data['telefono'])) {
            $errors[] = "Falta el número de celular";
        } elseif (!self::validatePhone($data['telefono'])) {
            $errors[] = "El número de celular debe tener 10 dígitos y comenzar con 3";
        } else {
            $validData['telefono'] = self::sanitizePhone($data['telefono']);
        }
        
        // Email
        if (empty($data['email'])) {
            $errors[] = "Falta el correo electrónico";
        } elseif (!self::validateEmail($data['email'])) {
            $errors[] = "El correo electrónico no es válido";
        } else {
            $validData['email'] = strtolower(trim($data['email']));
        }
        
        // Tipo (particular/seguro)
        if (empty($data['tipo'])) {
            $errors[] = "Falta indicar si es particular o por seguro";
        } else {
            $tipo = strtolower(trim($data['tipo']));
            if (strpos($tipo, 'particular') !== false) {
                $validData['tipo'] = 'particular';
            } elseif (strpos($tipo, 'seguro') !== false || strpos($tipo, 'eps') !== false) {
                $validData['tipo'] = 'seguro';
                // Extraer nombre del seguro si lo menciona
                $validData['nombre_seguro'] = self::extractInsuranceName($data['tipo']);
            } else {
                $errors[] = "Debe indicar 'particular' o 'seguro'";
            }
        }
        
        return [
            'valid' => empty($errors),
            'errors' => $errors,
            'data' => $validData
        ];
    }
    
    /**
     * Valida un nombre completo
     * @param string $name
     * @return bool
     */
    public static function validateFullName(string $name): bool
    {
        $name = trim($name);
        
        // Debe tener al menos 2 palabras
        $words = preg_split('/\s+/', $name);
        if (count($words) < 2) {
            return false;
        }
        
        // Solo debe contener letras y espacios
        return preg_match('/^[a-záéíóúñA-ZÁÉÍÓÚÑ\s]+$/u', $name);
    }
    
    /**
     * Valida un número de documento
     * @param string $document
     * @return bool
     */
    public static function validateDocument(string $document): bool
    {
        $doc = preg_replace('/[^0-9]/', '', $document);
        $length = strlen($doc);
        
        return $length >= 6 && $length <= 11;
    }
    
    /**
     * Valida un número de teléfono colombiano
     * @param string $phone
     * @return bool
     */
    public static function validatePhone(string $phone): bool
    {
        $phone = preg_replace('/[^0-9]/', '', $phone);
        
        // Debe tener 10 dígitos y comenzar con 3
        return strlen($phone) === 10 && $phone[0] === '3';
    }
    
    /**
     * Valida un correo electrónico
     * @param string $email
     * @return bool
     */
    public static function validateEmail(string $email): bool
    {
        return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
    }
    
    /**
     * Sanitiza un nombre
     * @param string $name
     * @return string
     */
    public static function sanitizeName(string $name): string
    {
        // Convertir a formato título (Primera Letra Mayúscula)
        $name = mb_convert_case(trim($name), MB_CASE_TITLE, 'UTF-8');
        
        // Remover espacios extras
        $name = preg_replace('/\s+/', ' ', $name);
        
        return $name;
    }
    
    /**
     * Sanitiza un documento
     * @param string $document
     * @return string
     */
    public static function sanitizeDocument(string $document): string
    {
        return preg_replace('/[^0-9]/', '', $document);
    }
    
    /**
     * Sanitiza un teléfono
     * @param string $phone
     * @return string
     */
    public static function sanitizePhone(string $phone): string
    {
        $phone = preg_replace('/[^0-9]/', '', $phone);
        
        // Si tiene 13 dígitos y empieza con 57, quitar el 57
        if (strlen($phone) === 12 && substr($phone, 0, 2) === '57') {
            $phone = substr($phone, 2);
        }
        
        return $phone;
    }
    
    /**
     * Extrae el nombre del seguro del texto
     * @param string $text
     * @return string|null
     */
    private static function extractInsuranceName(string $text): ?string
    {
        $insurances = [
            'colsanitas' => 'Colsanitas',
            'sanitas' => 'Sanitas',
            'sura' => 'Sura',
            'compensar' => 'Compensar',
            'salud total' => 'Salud Total',
            'famisanar' => 'Famisanar',
            'nueva eps' => 'Nueva EPS',
            'coomeva' => 'Coomeva'
        ];
        
        $textLower = strtolower($text);
        
        foreach ($insurances as $key => $name) {
            if (strpos($textLower, $key) !== false) {
                return $name;
            }
        }
        
        return null;
    }
    
    /**
     * Parsea datos del paciente desde un mensaje de texto
     * @param string $message
     * @return array
     */
    public static function parsePatientDataFromMessage(string $message): array
    {
        $data = [];
        
        // Dividir por líneas
        $lines = explode("\n", $message);
        
        foreach ($lines as $line) {
            $line = trim($line);
            
            if (empty($line)) {
                continue;
            }
            
            // Detectar nombre (primera línea larga con letras)
            if (empty($data['nombre']) && preg_match('/^[a-záéíóúñA-ZÁÉÍÓÚÑ\s]{5,}$/u', $line)) {
                $data['nombre'] = $line;
                continue;
            }
            
            // Detectar documento (números de 6-11 dígitos)
            if (empty($data['documento']) && preg_match('/(\d{6,11})/', $line, $matches)) {
                $data['documento'] = $matches[1];
                continue;
            }
            
            // Detectar teléfono (10 dígitos comenzando con 3)
            if (empty($data['telefono']) && preg_match('/(3\d{9})/', $line, $matches)) {
                $data['telefono'] = $matches[1];
                continue;
            }
            
            // Detectar email
            if (empty($data['email']) && preg_match('/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z]+)/', $line, $matches)) {
                $data['email'] = $matches[1];
                continue;
            }
            
            // Detectar dirección (contiene calle, carrera, etc.)
            if (empty($data['direccion']) && preg_match('/(calle|carrera|cra|cl|diagonal|transversal|avenida|av)/i', $line)) {
                $data['direccion'] = $line;
                continue;
            }
            
            // Detectar tipo (particular/seguro)
            if (empty($data['tipo']) && preg_match('/(particular|seguro|eps)/i', $line)) {
                $data['tipo'] = $line;
                continue;
            }
        }
        
        return $data;
    }
    
    /**
     * Genera un mensaje con los errores de validación
     * @param array $errors
     * @return string
     */
    public static function formatValidationErrors(array $errors): string
    {
        $message = "⚠️ Por favor corrige los siguientes datos:\n\n";
        
        foreach ($errors as $error) {
            $message .= "❌ $error\n";
        }
        
        $message .= "\nEnvía la información completa de nuevo.";
        
        return $message;
    }
    
    /**
     * Genera un resumen de los datos validados
     * @param array $data
     * @return string
     */
    public static function formatDataSummary(array $data): string
    {
        $message = "📋 DATOS RECIBIDOS:\n\n";
        $message .= "👤 Nombre: {$data['nombre']}\n";
        $message .= "🆔 Documento: {$data['documento']}\n";
        $message .= "📍 Dirección: {$data['direccion']}\n";
        $message .= "📱 Teléfono: {$data['telefono']}\n";
        $message .= "📧 Email: {$data['email']}\n";
        $message .= "💳 Tipo: {$data['tipo']}";
        
        if (isset($data['nombre_seguro'])) {
            $message .= " ({$data['nombre_seguro']})";
        }
        
        $message .= "\n\n¿Los datos son correctos?\nResponde: *SÍ* o *NO*";
        
        return $message;
    }
}
