<?php
declare(strict_types=1);

$phase = (string)($argv[1] ?? '');
$lane = (string)($argv[2] ?? '');
$marker = (string)($argv[3] ?? '');
if (!in_array($phase, ['--run', '--audit'], true) || !in_array($lane, ['B', 'C'], true)
    || !preg_match('/^CDXAPIGDS[A-F0-9]{8}$/D', $marker)
    || ($phase === '--run' && getenv('CDX_API_GOODS_RUN') !== 'OWNED_GOODS_SKU_SERVICE_V1')) {
    fwrite(STDERR, "DENIED business_http=0 business_dml=0\n"); exit(78);
}
if ($lane === 'B') {
    $config = parse_ini_file('/Users/wiscourper/Documents/workspace/zhct/zhctproject/ai_api/.env.local', true, INI_SCANNER_RAW)['DATABASE'] ?? null;
    if (!is_array($config) || strtolower((string)($config['TYPE'] ?? '')) !== 'mysql'
        || (string)($config['HOSTPORT'] ?? '') !== '3306'
        || hash('sha256', (string)($config['HOSTNAME'] ?? '')) !== '47e8be48b0cfd56dcdb9d9d426e6637b245f340b4efad4cd2f084ec5851ecc8e'
        || hash('sha256', (string)($config['DATABASE'] ?? '')) !== 'cf7756b3bb52cf72f625689134015b877fdab3ad8eb3bb2ddd962bb35f6efd66') {
        throw new RuntimeException('B code-local MySQL identity drift');
    }
    $db = new PDO('mysql:host=' . $config['HOSTNAME'] . ';port=3306;dbname=' . $config['DATABASE']
        . ';charset=' . $config['CHARSET'], $config['USERNAME'], $config['PASSWORD'],
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_CASE => PDO::CASE_LOWER]);
    $port = 18101;
} else {
    if (getenv('POC_DIALECT') !== 'dm' || getenv('POC_AI_HOST') !== '127.0.0.1'
        || getenv('POC_AI_PORT') !== '5238' || getenv('POC_AI_SCHEMA') !== 'AIZHCT_APP'
        || getenv('POC_AI_USER') !== 'AIZHCT_APP') {
        throw new RuntimeException('C isolated AI DM identity drift');
    }
    $db = new PDO('dm:host=127.0.0.1;port=5238;schema=AIZHCT_APP',
        getenv('POC_AI_USER'), getenv('POC_AI_PASSWORD'),
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_CASE => PDO::CASE_LOWER]);
    if ($db->query("SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")->fetchColumn() !== 'AIZHCT_APP') {
        throw new RuntimeException('C schema drift');
    }
    $port = 18102;
}
$one = static function (string $sql, array $args = []) use ($db) {
    $query = $db->prepare($sql);
    $query->execute($args);
    $row = $query->fetch(PDO::FETCH_ASSOC);
    return is_array($row) ? array_change_key_case($row, CASE_LOWER) : null;
};
$all = static function (string $sql, array $args = []) use ($db): array {
    $query = $db->prepare($sql);
    $query->execute($args);
    return array_map(static function (array $row): array {
        return array_change_key_case($row, CASE_LOWER);
    }, $query->fetchAll(PDO::FETCH_ASSOC));
};
$owned = static function () use ($all, $marker): array {
    $goods = $all('SELECT goods_id FROM yoshop_goods WHERE store_id=10001 AND goods_name=?', [$marker]);
    $ids = array_map(static function ($row): int { return (int)$row['goods_id']; }, $goods);
    if (!$ids) return ['goods' => 0, 'sku' => 0, 'service_rel' => 0];
    $idList = implode(',', $ids);
    return ['goods' => count($goods),
        'sku' => count($all('SELECT id FROM yoshop_goods_sku WHERE store_id=10001 AND goods_id IN (' . $idList . ')')),
        'service_rel' => count($all('SELECT id FROM yoshop_goods_service_rel WHERE store_id=10001 AND goods_id IN (' . $idList . ')'))];
};
$existing = $owned();
if ($phase === '--audit') {
    echo json_encode(['lane' => $lane, 'phase' => 'audit', 'marker' => $marker,
        'owned' => $existing, 'business_http' => 0, 'business_dml' => 0]), PHP_EOL;
    exit(array_sum($existing) === 0 ? 0 : 2);
}
if (array_sum($existing) !== 0) throw new RuntimeException('fixture marker already exists');
$service = $one('SELECT service_id,name FROM yoshop_goods_service'
    . ' WHERE store_id=10001 AND status=1 AND is_delete=0 ORDER BY sort ASC,service_id ASC');
if ($service === null) throw new RuntimeException('no natural enabled service source');
$naturalBefore = hash('sha256', json_encode([
    $all('SELECT goods_id,goods_name FROM yoshop_goods WHERE store_id=10001'
        . " AND goods_name NOT LIKE 'CDXAPIGDS%' ORDER BY goods_id"),
    $all('SELECT service_id,name FROM yoshop_goods_service WHERE store_id=10001'
        . ' AND status=1 AND is_delete=0 ORDER BY service_id'),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
$insertGoods = $db->prepare('INSERT INTO yoshop_goods'
    . ' (goods_name,content,status,store_id,create_time,update_time)'
    . ' VALUES (?,?,10,10001,?,?)');
$insertSku = $db->prepare('INSERT INTO yoshop_goods_sku'
    . ' (goods_id,goods_sku_id,goods_weight,goods_price,line_price,stock_num,store_id,create_time,update_time)'
    . ' VALUES (?,?,1.25,12.34,15.00,3,10001,?,?)');
$insertService = $db->prepare('INSERT INTO yoshop_goods_service_rel'
    . ' (goods_id,service_id,store_id,create_time) VALUES (?,?,10001,?)');
$http = static function (string $path) use ($port): array {
    $ctx = stream_context_create(['http' => [
        'method' => 'GET', 'header' => "platform: H5\r\n",
        'ignore_errors' => true, 'timeout' => 18, 'follow_location' => 0,
    ]]);
    $handle = @fopen('http://127.0.0.1:' . $port . $path, 'rb', false, $ctx);
    if (!is_resource($handle)) throw new RuntimeException('isolated AI HTTP unavailable');
    $raw = stream_get_contents($handle, 1048577);
    fclose($handle);
    if (!is_string($raw) || strlen($raw) > 1048576) throw new RuntimeException('HTTP response cap');
    $body = json_decode($raw, true);
    if (!is_array($body) || (int)($body['status'] ?? 0) !== 200) {
        throw new RuntimeException('business response failed at ' . $path
            . ' status=' . (string)($body['status'] ?? 'nonjson')
            . ' message=' . substr((string)($body['message'] ?? ''), 0, 100));
    }
    return $body;
};
$typeGraph = static function ($value) use (&$typeGraph) {
    if (!is_array($value)) return gettype($value);
    if (!$value) return [];
    if (array_keys($value) === range(0, count($value) - 1)) return array_map($typeGraph, $value);
    ksort($value);
    return array_map($typeGraph, $value);
};
$goodsId = 0;
$skuId = 0;
$relId = 0;
$committed = false;
$result = [];
$error = null;
try {
    $now = time();
    $db->beginTransaction();
    $insertGoods->execute([$marker, 'CDX API goods DB compatibility', $now, $now]);
    $row = $one('SELECT goods_id FROM yoshop_goods WHERE store_id=10001 AND goods_name=?', [$marker]);
    if ($row === null) throw new RuntimeException('owned goods insert absent');
    $goodsId = (int)$row['goods_id'];
    $insertSku->execute([$goodsId, '0', $now, $now]);
    $row = $one('SELECT id FROM yoshop_goods_sku WHERE store_id=10001 AND goods_id=?'
        . " AND goods_sku_id='0'", [$goodsId]);
    if ($row === null) throw new RuntimeException('owned SKU insert absent');
    $skuId = (int)$row['id'];
    $insertService->execute([$goodsId, (int)$service['service_id'], $now]);
    $row = $one('SELECT id FROM yoshop_goods_service_rel'
        . ' WHERE store_id=10001 AND goods_id=? AND service_id=?', [$goodsId, $service['service_id']]);
    if ($row === null) throw new RuntimeException('owned service relation absent');
    $relId = (int)$row['id'];
    $db->commit();
    $committed = true;
    $goodsSource = $one('SELECT goods_price_min,goods_price_max,line_price_min,line_price_max'
        . ' FROM yoshop_goods WHERE goods_id=? AND goods_name=?', [$goodsId, $marker]);
    $skuSource = $one('SELECT goods_price,line_price,stock_num FROM yoshop_goods_sku'
        . ' WHERE id=? AND goods_id=?', [$skuId, $goodsId]);
    if ($goodsSource === null || $skuSource === null) throw new RuntimeException('own price source absent');
    $assertMoney = static function (array $row, array $source, array $fields): void {
        foreach ($fields as $field) {
            if (!array_key_exists($field, $row) || !array_key_exists($field, $source)
                || $row[$field] !== bcadd((string)$source[$field], '0', 2)) {
                throw new RuntimeException('owned money response differs from original row');
            }
        }
    };
    $query = '?goodsId=' . $goodsId;
    $cases = [
        'list' => '/api/Goods/list?goodsName=' . rawurlencode($marker),
        'basic' => '/api/Goods/basic' . $query,
        'detail' => '/api/Goods/detail' . $query,
        'specData' => '/api/Goods/specData' . $query,
        'skuInfo' => '/api/Goods/skuInfo' . $query . '&goodsSkuId=0',
        'service' => '/api/goods.Service/list' . $query,
    ];
    foreach ($cases as $case => $path) {
        $body = $http($path);
        $data = $body['data'] ?? null;
        if (!is_array($data)) throw new RuntimeException('success data shape missing at ' . $case);
        $result[$case] = ['type_sha256' => hash('sha256', json_encode($typeGraph($data))),
            'business_status' => 200];
        if ($case === 'list') {
            $items = $data['list']['data'] ?? null;
            if (!is_array($items) || count($items) !== 1
                || (int)($data['list']['total'] ?? -1) !== 1
                || (int)($items[0]['goods_id'] ?? 0) !== $goodsId
                || (string)($items[0]['goods_name'] ?? '') !== $marker) {
                throw new RuntimeException('owned goods list source mismatch');
            }
            $assertMoney($items[0], $goodsSource,
                ['goods_price_min', 'goods_price_max', 'line_price_min', 'line_price_max']);
        } elseif ($case === 'basic' || $case === 'detail') {
            $item = $data['detail'] ?? null;
            if (!is_array($item) || (int)($item['goods_id'] ?? 0) !== $goodsId
                || (string)($item['goods_name'] ?? '') !== $marker) {
                throw new RuntimeException('owned goods detail source mismatch');
            }
            $assertMoney($item, $goodsSource,
                ['goods_price_min', 'goods_price_max', 'line_price_min', 'line_price_max']);
        } elseif ($case === 'service') {
            $items = $data['list'] ?? null;
            if (!is_array($items) || count($items) !== 1
                || (int)($items[0]['service_id'] ?? 0) !== (int)$service['service_id']
                || (string)($items[0]['name'] ?? '') !== (string)$service['name']) {
                throw new RuntimeException('owned service source mismatch');
            }
        } elseif ($case === 'specData') {
            $items = $data['specData']['skuList'] ?? null;
            if (!is_array($items) || count($items) !== 1
                || (int)($items[0]['id'] ?? 0) !== $skuId) {
                throw new RuntimeException('owned SKU spec source mismatch');
            }
            $assertMoney($items[0], $skuSource, ['goods_price', 'line_price']);
        } elseif ($case === 'skuInfo') {
            $item = $data['skuInfo'] ?? null;
            if (!is_array($item) || (int)($item['id'] ?? 0) !== $skuId) {
                throw new RuntimeException('owned SKU info source mismatch');
            }
            $assertMoney($item, $skuSource, ['goods_price', 'line_price']);
        }
    }
    if ($owned() !== ['goods' => 1, 'sku' => 1, 'service_rel' => 1]) {
        throw new RuntimeException('owned rows changed during HTTP reads');
    }
} catch (Throwable $caught) {
    $error = $caught;
} finally {
    if ($db->inTransaction()) $db->rollBack();
    if ($committed) {
        $db->beginTransaction();
        try {
            $deletes = [
                ['DELETE FROM yoshop_goods_service_rel WHERE id=? AND goods_id=? AND store_id=10001', [$relId, $goodsId]],
                ['DELETE FROM yoshop_goods_sku WHERE id=? AND goods_id=? AND store_id=10001', [$skuId, $goodsId]],
                ['DELETE FROM yoshop_goods WHERE goods_id=? AND goods_name=? AND store_id=10001', [$goodsId, $marker]],
            ];
            foreach ($deletes as $target) {
                $stmt = $db->prepare($target[0]);
                $stmt->execute($target[1]);
            }
            if (array_sum($owned()) !== 0) throw new RuntimeException('owned three-row cleanup failed');
            $db->commit();
        } catch (Throwable $cleanupError) {
            $db->rollBack();
            throw $cleanupError;
        }
    }
}
if (array_sum($owned()) !== 0) throw new RuntimeException('independent own marker postcheck failed');
$naturalAfter = hash('sha256', json_encode([
    $all('SELECT goods_id,goods_name FROM yoshop_goods WHERE store_id=10001'
        . " AND goods_name NOT LIKE 'CDXAPIGDS%' ORDER BY goods_id"),
    $all('SELECT service_id,name FROM yoshop_goods_service WHERE store_id=10001'
        . ' AND status=1 AND is_delete=0 ORDER BY service_id'),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
if ($naturalBefore !== $naturalAfter) throw new RuntimeException('natural goods/service source changed');
if ($error !== null) throw $error;
echo json_encode(['lane' => $lane, 'marker' => $marker,
    'goods_id_present_during_run' => $goodsId > 0,
    'sku_id_present_during_run' => $skuId > 0,
    'service_relation_present_during_run' => $relId > 0,
    'cases' => $result, 'owned_cleanup_independent_zero' => true,
    'business_dml' => 'three-owned-inserts-three-owned-deletes'],
    JSON_UNESCAPED_SLASHES), PHP_EOL;
