<?php
/**
 * Clase ligera para leer metadatos DICOM sin dependencias externas.
 */
class DicomReader {
    private static $tags = [
        '00100010' => 'paciente',
        '00100020' => 'paciente_id',
        '00080020' => 'fecha_estudio',
        '00080030' => 'hora_estudio',
        '00080060' => 'modalidad',
        '00081030' => 'descripcion',
        '0020000d' => 'study_uid'
    ];

    public static function extractMetadata($filename) {
        if (!file_exists($filename) || filesize($filename) < 132) return null;
        
        $handle = fopen($filename, "rb");
        if (!$handle) return null;

        // Verificar preámbulo DICOM (128 bytes + "DICM")
        fseek($handle, 128);
        if (fread($handle, 4) !== "DICM") {
            fclose($handle);
            return null;
        }
        
        $metadata = [
            'paciente' => 'Desconocido',
            'paciente_id' => 'SN',
            'fecha_estudio' => date('Ymd'),
            'hora_estudio' => '000000',
            'modalidad' => 'OT',
            'descripcion' => '',
            'study_uid' => ''
        ];

        $foundCount = 0;
        $fileSize = filesize($filename);

        // Escaneo secuencial (limitado a los primeros 64KB para eficiencia)
        $limit = min($fileSize - 8, 65536);
        while (ftell($handle) < $limit) {
            $rawGroup = fread($handle, 2);
            if (strlen($rawGroup) < 2) break;
            $group = sprintf("%04x", unpack("v", $rawGroup)[1]);
            
            $rawElem = fread($handle, 2);
            if (strlen($rawElem) < 2) break;
            $element = sprintf("%04x", unpack("v", $rawElem)[1]);
            
            $tag = $group . $element;

            // Leer VR (2 bytes)
            $vr = fread($handle, 2);
            if (strlen($vr) < 2) break;
            
            // Lógica para determinar longitud basada en VR (Explicit VR)
            if (in_array($vr, ['OB', 'OW', 'SQ', 'UN', 'UT'])) {
                fseek($handle, 2, SEEK_CUR); // Reservados
                $rawLen = fread($handle, 4);
                if (strlen($rawLen) < 4) break;
                $length = unpack("V", $rawLen)[1];
            } elseif (ctype_upper(substr($vr, 0, 1)) && ctype_upper(substr($vr, 1, 1))) {
                // Posible VR de 2 letras (Explicit)
                $rawLen = fread($handle, 2);
                if (strlen($rawLen) < 2) break;
                $length = unpack("v", $rawLen)[1];
            } else {
                // No parece Explicit VR, retroceder y tratar como Implicit (4 bytes de longitud)
                fseek($handle, -2, SEEK_CUR);
                $rawLen = fread($handle, 4);
                if (strlen($rawLen) < 4) break;
                $length = unpack("V", $rawLen)[1];
            }

            if (isset(self::$tags[$tag])) {
                if ($length > 0 && $length < 1024) {
                    $value = trim(fread($handle, $length));
                    $cleanValue = str_replace(["^", "\0"], [" ", ""], $value);
                    $cleanValue = preg_replace('/\s+/', ' ', $cleanValue);
                    $metadata[self::$tags[$tag]] = trim($cleanValue);
                }
                $foundCount++;
                if ($foundCount >= count(self::$tags)) break;
            } else {
                if ($length > 0 && $length < 1000000) {
                    fseek($handle, $length, SEEK_CUR);
                } else if ($length > 1000000) {
                    break; // Evitar saltos gigantes o errores
                }
            }
        }

        fclose($handle);
        return $metadata;
    }

    /**
     * Busca archivos DICOM. Soporta .dcm y archivos sin extensión o con nombres de UID.
     */
    public static function getMetadataFromFolder($dir) {
        $it = new RecursiveDirectoryIterator($dir);
        foreach (new RecursiveIteratorIterator($it) as $file) {
            if ($file->isFile()) {
                $ext = strtolower($file->getExtension());
                $name = $file->getFilename();
                
                // Intentar leer si es .dcm O si tiene formato de UID (muchos puntos o sin extensión)
                if ($ext === 'dcm' || $ext === '' || substr_count($name, '.') > 3) {
                    $meta = self::extractMetadata($file->getPathname());
                    if ($meta && ($meta['study_uid'] != '' || $meta['paciente'] != 'Desconocido')) {
                        return $meta;
                    }
                }
            }
        }
        return null;
    }
}
