<?php
declare(strict_types=1);require __DIR__.'/cli-common.php';
$check($dm&&$lane==='C','Only approved nonproduction DM C schema repair');
$journalFile=$runtime.'/img-ddl-journal.json';$check(!file_exists($journalFile),'No schema replay after success or unknown outcome');
$baseline=json_decode(file_get_contents(__DIR__.'/img-preflight-C.json'),true);$expectedHash='1fd0eef856df45a66f6c2f34c11022d9e8a65c960df641edcdf0a583ec5ff2a3';
$metadata=static function($pdo)use($query){return $query($pdo,'SELECT COLUMN_NAME,DATA_TYPE,DATA_LENGTH,CHAR_LENGTH,CHAR_USED,DATA_PRECISION,DATA_SCALE,NULLABLE,DATA_DEFAULT FROM USER_TAB_COLUMNS WHERE TABLE_NAME=? ORDER BY COLUMN_ID',['YOSHOP_STAFF']);};
$objects=static function($pdo)use($query){return [
 'indexes'=>$query($pdo,'SELECT INDEX_NAME,INDEX_TYPE,UNIQUENESS,STATUS FROM USER_INDEXES WHERE TABLE_NAME=? ORDER BY INDEX_NAME',['YOSHOP_STAFF']),
 'index_columns'=>$query($pdo,'SELECT INDEX_NAME,COLUMN_NAME,COLUMN_POSITION FROM USER_IND_COLUMNS WHERE TABLE_NAME=? ORDER BY INDEX_NAME,COLUMN_POSITION',['YOSHOP_STAFF']),
 'constraints'=>$query($pdo,'SELECT CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS,SEARCH_CONDITION,R_CONSTRAINT_NAME FROM USER_CONSTRAINTS WHERE TABLE_NAME=? ORDER BY CONSTRAINT_NAME',['YOSHOP_STAFF']),
 'constraint_columns'=>$query($pdo,'SELECT CONSTRAINT_NAME,COLUMN_NAME,POSITION FROM USER_CONS_COLUMNS WHERE TABLE_NAME=? ORDER BY CONSTRAINT_NAME,POSITION',['YOSHOP_STAFF']),
 'triggers'=>$query($pdo,'SELECT * FROM USER_TRIGGERS WHERE TABLE_NAME=? ORDER BY TRIGGER_NAME',['YOSHOP_STAFF'])];};
$projection=static function($pdo)use($baseline){$s=$pdo->prepare($baseline['original_projection']['sql']);$s->execute();$h=hash_init('sha256');$n=0;while($r=$s->fetch(PDO::FETCH_NUM)){foreach($r as &$v)if(is_resource($v))$v=stream_get_contents($v);unset($v);hash_update($h,serialize($r)."\n");++$n;}return ['rows'=>$n,'sha256'=>hash_final($h)];};
$canonical=static function($value)use(&$canonical){if(!is_array($value))return $value;foreach($value as &$child)$child=$canonical($child);unset($child);if(array_keys($value)!==range(0,count($value)-1))ksort($value);return $value;};
$same=static function($a,$b)use($canonical){return $canonical($a)===$canonical($b);};
$before=$metadata($db);$beforeObjects=$objects($db);$beforeRows=$projection($db);
$check(count($before)===20&&!in_array('IMG',array_column($before,'column_name'),true),'Fresh original20 / IMG absent');
$check($same($before,$baseline['metadata'])&&$same($beforeObjects,$baseline['objects']),'Fresh full original20 metadata and every original object');
$check($beforeRows===['rows'=>1775,'sha256'=>$expectedHash],'Fresh all original1775 full20 exact');
$ddl=["ALTER TABLE AIZHCT_APP.YOSHOP_STAFF ADD IMG VARCHAR(256 CHAR) DEFAULT '' NOT NULL","COMMENT ON COLUMN AIZHCT_APP.YOSHOP_STAFF.IMG IS '课程图片(OSS地址)'"];
$journal=['before_metadata'=>$before,'before_objects'=>$beforeObjects,'before_projection'=>$beforeRows,'statements'=>[],'success'=>false];$persist('img-ddl-journal.json',$journal);
try{
 foreach($ddl as $sql){$i=count($journal['statements']);$journal['statements'][]=['sql'=>$sql,'sent'=>true,'returned'=>false];$persist('img-ddl-journal.json',$journal);$result=$db->exec($sql);$journal['statements'][$i]['returned']=true;$journal['statements'][$i]['result']=$result;$persist('img-ddl-journal.json',$journal);}
 $independent=$connect();$after=$metadata($independent);$afterObjects=$objects($independent);$afterRows=$projection($independent);
 $check(count($after)===21&&$same(array_slice($after,0,20),$before),'Only new21st metadata column');
 $img=$after[20];$check($img['column_name']==='IMG'&&strtoupper($img['data_type'])==='VARCHAR'&&(int)$img['char_length']===256&&(int)$img['data_length']===1024&&$img['char_used']==='C'&&$img['nullable']==='N'&&trim($img['data_default'])==="''",'IMG exact source length/CHAR/NN/default');
 $check($same($afterObjects,$beforeObjects)&&$afterRows===$beforeRows,'All old objects and original1775x20 preserved');
 $comment=$query($independent,'SELECT COMMENTS FROM USER_COL_COMMENTS WHERE TABLE_NAME=? AND COLUMN_NAME=?',['YOSHOP_STAFF','IMG']);$check(count($comment)===1&&$comment[0]['comments']==='课程图片(OSS地址)','Exact source comment');
 $invalid=$query($independent,"SELECT COUNT(*) n FROM AIZHCT_APP.YOSHOP_STAFF WHERE IMG IS NULL OR IMG<>''");$check((int)$invalid[0]['n']===0,'Every original row new IMG empty');
 $journal['success']=true;$journal['after_metadata']=$after;$journal['after_objects']=$afterObjects;$journal['after_projection']=$afterRows;$persist('img-ddl-journal.json',$journal);
 $out=['lane'=>'C','success'=>true,'DDL'=>2,'DML'=>0,'HTTP'=>0,'original_rows'=>1775,'original20_sha256'=>$afterRows['sha256'],'original_metadata_objects_unchanged'=>true,'new_column'=>['name'=>'IMG','characters'=>256,'bytes'=>1024,'character_unit'=>'CHAR','nullable'=>false,'default'=>'','comment'=>'课程图片(OSS地址)'],'all_original_IMG_empty'=>true,'independent_new_PDO'=>true];file_put_contents(__DIR__.'/img-repair-result.json',json_encode($out,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE));echo json_encode($out,JSON_UNESCAPED_UNICODE),"\n";
}catch(Throwable $e){$journal['error']=['class'=>get_class($e),'code'=>$e->getCode(),'message'=>$e->getMessage()];$persist('img-ddl-journal.json',$journal);throw $e;}
