<?php
/**
 * Arsenal Nexora - smart item options catalog builder.
 * CLI only. Runtime never parses the source XML files.
 *
 * Usage:
 * php tools_build_option_catalog.php Ancient_Items.xml Ancient_Type.xml Harmony_Attack.xml Harmony_Defensive.xml Harmony_Staffs.xml Socket_Options.xml
 */
if(PHP_SAPI !== 'cli') { http_response_code(404); exit; }
if($argc < 7) {
    fwrite(STDERR, "Uso: php ".$argv[0]." Ancient_Items.xml Ancient_Type.xml Harmony_Attack.xml Harmony_Defensive.xml Harmony_Staffs.xml Socket_Options.xml\n");
    exit(1);
}
$paths = array(
    'ancient_items'=>$argv[1],
    'ancient_types'=>$argv[2],
    'harmony_attack'=>$argv[3],
    'harmony_defensive'=>$argv[4],
    'harmony_staffs'=>$argv[5],
    'socket_options'=>$argv[6],
);
foreach($paths as $label=>$path) {
    if(!is_file($path) || !is_readable($path)) {
        fwrite(STDERR, "No se puede leer {$label}: {$path}\n");
        exit(1);
    }
}
$target = __DIR__.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'item-options.json';

function itemshopRead($path) {
    $content = file_get_contents($path);
    if(!is_string($content) || $content === '') throw new RuntimeException('Archivo vacío: '.$path);
    return $content;
}

function itemshopAttrs($text) {
    $attrs = array();
    if(preg_match_all('/([A-Za-z0-9_]+)\s*=\s*["\']\s*([^"\']*?)\s*["\']/u', $text, $pairs, PREG_SET_ORDER)) {
        foreach($pairs as $pair) $attrs[$pair[1]] = trim($pair[2]);
    }
    return $attrs;
}

function itemshopParseAncientTypes($content) {
    $types = array();
    if(preg_match_all('/<Item\s+([^>]*?)\s*\/\s*>/u', $content, $matches)) {
        foreach($matches[1] as $text) {
            $a = itemshopAttrs($text);
            if(!isset($a['Index'],$a['Name'])) continue;
            $idx = (int)$a['Index'];
            $name = trim($a['Name']);
            if($idx > 0 && $idx <= 255 && $name !== '') $types[(string)$idx] = $name;
        }
    }
    ksort($types, SORT_NUMERIC);
    return $types;
}

function itemshopParseAncientItems($content, $types) {
    $byCode = array();
    if(preg_match_all('/<Item\s+([^>]*?)\s*\/\s*>/u', $content, $matches)) {
        foreach($matches[1] as $text) {
            $a = itemshopAttrs($text);
            if(!isset($a['Type'],$a['Index'],$a['Value1'],$a['Value2'])) continue;
            $section = (int)$a['Type'];
            $index = (int)$a['Index'];
            if($section < 0 || $section > 15 || $index < 0 || $index > 511) continue;
            $v1 = (int)$a['Value1'];
            $v2 = (int)$a['Value2'];
            $row = array('a'=>null,'b'=>null);
            if($v1 > 0) $row['a'] = array('type'=>$v1,'name'=>isset($types[(string)$v1]) ? $types[(string)$v1] : ('Ancient #'.$v1));
            if($v2 > 0) $row['b'] = array('type'=>$v2,'name'=>isset($types[(string)$v2]) ? $types[(string)$v2] : ('Ancient #'.$v2));
            if($row['a'] !== null || $row['b'] !== null) $byCode[$section.':'.$index] = $row;
        }
    }
    return $byCode;
}

function itemshopParseHarmony($content) {
    $sections = array();
    if(preg_match_all('/<Section\s+([^>]*?)>(.*?)<\/Section>/us', $content, $sectionMatches, PREG_SET_ORDER)) {
        foreach($sectionMatches as $sm) {
            $sa = itemshopAttrs($sm[1]);
            if(!isset($sa['Index'],$sa['Name'])) continue;
            $type = (int)$sa['Index'];
            if($type < 1 || $type > 15) continue;
            $levels = array();
            if(preg_match_all('/<Item\s+([^>]*?)\s*\/\s*>/u', $sm[2], $itemMatches)) {
                foreach($itemMatches[1] as $text) {
                    $a = itemshopAttrs($text);
                    if(!isset($a['Level'],$a['Name'])) continue;
                    $level = (int)$a['Level'];
                    if($level < 0 || $level > 15) continue;
                    $levels[] = array('level'=>$level,'raw'=>(($type & 0x0F) << 4) | ($level & 0x0F),'name'=>trim($a['Name']));
                }
            }
            if($levels) $sections[] = array('type'=>$type,'name'=>trim($sa['Name']),'levels'=>$levels);
        }
    }
    return $sections;
}

function itemshopParseSocket($content) {
    $options = array();
    $bonuses = array();
    if(preg_match_all('/<Item\s+([^>]*?)\s*\/\s*>/u', $content, $matches)) {
        foreach($matches[1] as $text) {
            $a = itemshopAttrs($text);
            if(!isset($a['Index'],$a['Type'],$a['Name'])) continue;
            $index = (int)$a['Index'];
            $type = (int)$a['Type'];
            if($index < 0 || $index > 255 || $type < 0 || $type > 3) continue;
            $row = array(
                'index'=>$index,
                'type'=>$type,
                'element'=>isset($a['Element']) ? (int)$a['Element'] : 0,
                'name'=>trim($a['Name']),
                'values'=>array(),
            );
            for($i=1;$i<=5;$i++) if(isset($a['Val'.$i])) $row['values'][] = (int)$a['Val'.$i];
            if($type === 3) $bonuses[] = $row; else $options[] = $row;
        }
    }
    usort($options, function($a,$b){ return $a['index'] <=> $b['index']; });
    usort($bonuses, function($a,$b){ return $a['index'] <=> $b['index']; });
    return array('options'=>$options,'bonuses'=>$bonuses);
}

try {
    $ancientTypes = itemshopParseAncientTypes(itemshopRead($paths['ancient_types']));
    $ancientItems = itemshopParseAncientItems(itemshopRead($paths['ancient_items']), $ancientTypes);
    $socket = itemshopParseSocket(itemshopRead($paths['socket_options']));

    // Excellent profiles 1 and 2 use the established 6-bit DbVersion mapping.
    // Profiles 3-5 are kept type-aware but locked: the supplied Items.xml identifies the profile,
    // not the per-bit semantics. Arsenal does not invent selectable bits without a verified map.
    $excellent = array(
        '0'=>array('name'=>'Sin Excellent','options'=>array()),
        '1'=>array('name'=>'Armas','options'=>array(
            array('bit'=>1,'name'=>'Recuperación de Mana tras eliminar monstruos'),
            array('bit'=>2,'name'=>'Recuperación de HP tras eliminar monstruos'),
            array('bit'=>4,'name'=>'Velocidad de ataque / magia +7'),
            array('bit'=>8,'name'=>'Daño / magia +2%'),
            array('bit'=>16,'name'=>'Daño + nivel/20'),
            array('bit'=>32,'name'=>'Excellent Damage Rate +10%'),
        )),
        '2'=>array('name'=>'Armaduras / escudos','options'=>array(
            array('bit'=>1,'name'=>'Zen obtenido tras cazar +40%'),
            array('bit'=>2,'name'=>'Defense Success Rate +10%'),
            array('bit'=>4,'name'=>'Reflect Damage +5%'),
            array('bit'=>8,'name'=>'Damage Decrease +4%'),
            array('bit'=>16,'name'=>'Max Mana +4%'),
            array('bit'=>32,'name'=>'Max HP +4%'),
        )),
        '3'=>array('name'=>'Alas nivel 2 · mapa Excellent pendiente','options'=>array()),
        '4'=>array('name'=>'Alas nivel 3 · mapa Excellent pendiente','options'=>array()),
        '5'=>array('name'=>'Fenrir · mapa Excellent pendiente','options'=>array()),
    );

    $payload = array(
        'version'=>1,
        'source'=>'XML del Warehouse Editor + mapeo DbVersion 3 validado',
        'source_hashes'=>(function() use ($paths) {
            $hashes = array();
            foreach($paths as $label=>$path) $hashes[$label] = hash_file('sha256', $path);
            return $hashes;
        })(),
        'excellent_profiles'=>$excellent,
        'ancient'=>array('types'=>$ancientTypes,'by_code'=>$ancientItems),
        'harmony'=>array(
            'attack'=>itemshopParseHarmony(itemshopRead($paths['harmony_attack'])),
            'defensive'=>itemshopParseHarmony(itemshopRead($paths['harmony_defensive'])),
            'staffs'=>itemshopParseHarmony(itemshopRead($paths['harmony_staffs'])),
        ),
        'socket'=>$socket,
    );
    $json = json_encode($payload, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
    if($json === false) throw new RuntimeException('No se pudo serializar el catálogo de opciones.');
    if(!is_dir(dirname($target)) && !mkdir(dirname($target), 0755, true)) throw new RuntimeException('No se pudo crear data/.');
    if(file_put_contents($target, $json, LOCK_EX) === false) throw new RuntimeException('No se pudo escribir '.$target);
    echo 'Catálogo de opciones generado: '.count($ancientItems).' códigos Ancient, '.count($socket['options']).' opciones Socket, '.count($socket['bonuses'])." bonus Socket.\n";
} catch(Throwable $e) {
    fwrite(STDERR, $e->getMessage()."\n");
    exit(2);
}
