<?php
declare(strict_types=1);

use app\cron\command\MqttServer;
use think\App;
use think\Cache;
use think\Db;
use think\console\Output;

$storeRoot = '/workspace/zhct/zhctproject/store';

define('APP_PATH', $storeRoot . '/application/');
require $storeRoot . '/env.php';
require $storeRoot . '/thinkphp/base.php';
App::initCommon();

$marker = 'JSR_REAL_HY093_' . date('YmdHis') . '_' . mt_rand(1000, 9999);
$shortMarker = 'JSR' . substr($marker, -12);
$now = date('Y-m-d H:i:s');
$payload = [
    'create_time' => '2026-06-16 10:31:23',
    'msgid' => '000261781577083183',
    'action' => 'consume',
    'order_type' => getenv('REPRO_ORDER_TYPE') ?: '1',
    'publish_topic' => 'zhct_jsr/zhct_jsr/p2p/GID_zhct_jsr@@@consume_work_0',
    'subscribe_topic' => 'zhct_jsr/zhct_jsr/p2p/GID_zhct_jsr@@@00026',
    'account' => 'admin',
    'key' => 'codex-jsr-real-hy093-key',
    'pwd' => 'codex-jsr-real-hy093-pwd',
    'card_id' => '3455500610',
    'equipment_code' => '00026',
    'dishes' => [
        [
            'uuid' => 'custom_dish',
            'number' => '1',
            'money' => '3.00',
        ],
    ],
    'paycode' => '',
    'money' => '3.00',
    'staff_uuid' => '',
    '_mqtt_device_id' => 'dev2_consume_work_1',
    '_mqtt_sender_device_id' => '00026',
    '_mqtt_topic' => 'zhct_jsr/zhct_jsr/p2p/GID_zhct_jsr@@@consume_work_0',
];

$fixture = [
    'restaurant_id' => 0,
    'equipment_id' => 0,
    'strategy_id' => 0,
    'user_id' => 0,
    'staff_uuid' => '',
    'department_uuid' => '',
];

function codex_guid(): string
{
    if (function_exists('guid')) {
        return (string)guid();
    }
    return strtoupper(sprintf(
        '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
        mt_rand(0, 0xffff),
        mt_rand(0, 0xffff),
        mt_rand(0, 0xffff),
        mt_rand(0, 0x0fff) | 0x4000,
        mt_rand(0, 0x3fff) | 0x8000,
        mt_rand(0, 0xffff),
        mt_rand(0, 0xffff),
        mt_rand(0, 0xffff)
    ));
}

function codex_insert_from_sample(string $table, array $changes, array $fallback): int
{
    $sample = Db::name($table)->limit(1)->find();
    $row = is_array($sample) && !empty($sample) ? $sample : $fallback;
    unset($row['id']);
    $row = array_merge($row, $changes);
    return (int)Db::name($table)->insertGetId($row);
}

function codex_delete_redis_keys(array $keys): void
{
    try {
        $redis = getRedis();
        if ($redis instanceof Redis) {
            foreach ($keys as $key) {
                $redis->del($key);
            }
        }
    } catch (Throwable $e) {
        echo 'REDIS_KEY_DELETE_WARNING=' . $e->getMessage() . PHP_EOL;
    }

    foreach ($keys as $key) {
        try {
            Cache::rm($key);
        } catch (Throwable $e) {
            echo 'CACHE_KEY_DELETE_WARNING=' . $key . ':' . $e->getMessage() . PHP_EOL;
        }
    }
}

function codex_call_private($object, string $methodName, array $args = [])
{
    $method = new ReflectionMethod($object, $methodName);
    $method->setAccessible(true);
    return $method->invokeArgs($object, $args);
}

echo 'env=' . TP_ENV . PHP_EOL;
echo 'business=' . BUSINESS . PHP_EOL;
echo 'database=' . config('database.database') . PHP_EOL;
echo 'marker=' . $marker . PHP_EOL;
echo 'payload=' . json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;

try {
    $fixture['staff_uuid'] = codex_guid();
    $fixture['department_uuid'] = codex_guid();
    $identityId = 1;
    $departmentUuid = 'F7344EC0-5203-330E-7701-4883DEE5601D';
    $fixture['department_uuid'] = $departmentUuid;

    $fixture['restaurant_id'] = codex_insert_from_sample('restaurants', [
        'uuid' => codex_guid(),
        'name' => '一楼超市_' . $marker,
        'status' => 1,
        'is_delete' => 2,
        'stall_type' => 1,
        'is_order' => 2,
        'restaurant_shop_id' => 2,
        'morning_start' => '00:00',
        'morning_end' => '10:00',
        'noon_start' => '10:01',
        'noon_end' => '16:00',
        'night_start' => '16:01',
        'night_end' => '19:30',
        'create_by' => 'codex',
        'introduction' => $marker,
    ], [
        'uuid' => codex_guid(),
        'restaurant_shop_id' => 2,
        'status' => 1,
        'name' => '一楼超市_' . $marker,
        'location' => '',
        'responsible' => '',
        'file_path' => '',
        'is_delete' => 2,
        'create_by' => 'codex',
        'introduction' => $marker,
        'is_order' => 2,
        'stall_type' => 1,
        'book_rules' => '',
        'order_rules' => '',
    ]);

    $fixture['equipment_id'] = codex_insert_from_sample('equipment', [
        'code' => $payload['equipment_code'],
        'name' => '一楼超市_' . $shortMarker,
        'type' => 9,
        'restaurant_id' => $fixture['restaurant_id'],
        'status' => 1,
        'del_flag' => 0,
        'create_time' => $now,
        'create_by' => 'codex',
        'update_time' => $now,
        'update_by' => 'codex',
    ], [
        'code' => $payload['equipment_code'],
        'name' => '一楼超市_' . $shortMarker,
        'type' => 9,
        'restaurant_id' => $fixture['restaurant_id'],
        'status' => 1,
        'del_flag' => 0,
        'matecode' => '',
        'communicationkey' => '',
        'create_time' => $now,
        'create_by' => 'codex',
        'update_time' => $now,
        'update_by' => 'codex',
    ]);
    Db::name('equipment')
        ->where('code', $payload['equipment_code'])
        ->where('id', '<>', $fixture['equipment_id'])
        ->update(['del_flag' => 1, 'update_time' => $now, 'update_by' => 'codex_hy093']);

    Db::name('api_auth')->insert([
        'account' => $payload['account'],
        'pwd' => $payload['pwd'],
        'key' => $payload['key'],
        'type' => 1,
        'restaurant_id' => $fixture['restaurant_id'],
        'equipment_id' => $fixture['equipment_id'],
        'start_time' => '2000-01-01 00:00:00',
        'end_time' => '2099-12-31 23:59:59',
        'status' => 1,
        'remark' => $marker,
        'create_by' => 'codex',
        'create_time' => $now,
        'update_time' => $now,
    ]);

    codex_insert_from_sample('staff', [
        'uuid' => $fixture['staff_uuid'],
        'name' => '刘平(LD)',
        'mobile' => '15862975956',
        'account' => '15862975956_' . substr($marker, -4),
        'identity_category_id' => $identityId,
        'restaurant_id' => $fixture['restaurant_id'],
        'is_show' => 1,
        'status' => 1,
        'ai_user_id' => 23,
        'department_id' => 0,
        'department_name' => '金斯瑞真实复现部门',
        'create_time' => $now,
        'create_by' => 'codex',
        'personnel_umber' => substr($marker, -16),
    ], [
        'uuid' => $fixture['staff_uuid'],
        'station_uuid' => '',
        'name' => '刘平(LD)',
        'birthday' => '2000-01-01',
        'sport_uuid' => '',
        'sport_event_uuid' => '',
        'in_time' => '2000-01-01',
        'create_time' => $now,
        'create_by' => 'codex',
        'personnel_umber' => substr($marker, -16),
        'permanent_address' => '',
        'coach_name' => '',
        'sport_year' => '',
        'restaurant_id' => $fixture['restaurant_id'],
        'identity_category_id' => $identityId,
    ]);

    $fixture['user_id'] = codex_insert_from_sample('user', [
        'uuid' => codex_guid(),
        'account' => 'jsr_hy093_' . substr($marker, -12),
        'name' => '刘平(LD)',
        'staff_uuid' => $fixture['staff_uuid'],
        'mobile' => '15862975956',
        'balance' => '0.00',
        'ai_user_id' => 23,
        'is_delete' => 0,
        'create_time' => $now,
        'create_by' => 'codex',
    ], [
        'uuid' => codex_guid(),
        'account' => 'jsr_hy093_' . substr($marker, -12),
        'pwd' => '',
        'salt' => '',
        'name' => '刘平(LD)',
        'create_time' => $now,
        'create_by' => 'codex',
        'staff_uuid' => $fixture['staff_uuid'],
        'balance' => '0.00',
        'is_delete' => 0,
        'ai_user_id' => 23,
    ]);

    Db::name('staff_card')->insert([
        'staff_uuid' => $fixture['staff_uuid'],
        'card_id' => $payload['card_id'],
        'card_status' => 1,
        'is_cancel' => 0,
        'cost' => '0.00',
        'store_id' => 10001,
        'create_by' => 'codex',
        'is_delete' => 0,
        'create_time' => $now,
        'update_time' => $now,
    ]);
    Db::name('staff_card')
        ->where('card_id', $payload['card_id'])
        ->where('staff_uuid', '<>', $fixture['staff_uuid'])
        ->update(['is_delete' => 1, 'update_time' => $now]);

    Db::name('staff_department')->insert([
        'department_uuid' => $departmentUuid,
        'staff_uuid' => $fixture['staff_uuid'],
        'is_charge' => 0,
        'create_time' => $now,
        'create_by' => 'codex',
    ]);

    $fixture['strategy_id'] = (int)Db::name('marketing_strategy')->insertGetId([
        'strategy_name' => '镇江档口午餐优惠2元_' . $marker,
        'priority' => 1,
        'strategy_type' => 2,
        'strategy_value' => '2.00',
        'is_first_consume_only' => 1,
        'application_scene' => 0,
        'application_scenario' => 1,
        'time_range_mode' => 1,
        'status' => 1,
        'effective_type' => 1,
        'effective_start' => '2026-06-15',
        'effective_end' => '2026-06-17',
        'remark' => $marker,
        'store_id' => 10001,
        'create_by' => 'codex',
        'update_by' => 'codex',
        'is_delete' => 0,
        'create_time' => $now,
        'update_time' => $now,
    ]);

    Db::name('marketing_strategy_identity')->insert([
        'strategy_id' => $fixture['strategy_id'],
        'identity_id' => $identityId,
        'store_id' => 10001,
        'create_time' => $now,
    ]);
    Db::name('marketing_strategy_department')->insert([
        'strategy_id' => $fixture['strategy_id'],
        'department_uuid' => $departmentUuid,
        'store_id' => 10001,
        'create_time' => $now,
    ]);
    Db::name('marketing_strategy_restaurant')->insert([
        'strategy_id' => $fixture['strategy_id'],
        'restaurant_id' => $fixture['restaurant_id'],
        'store_id' => 10001,
        'create_time' => $now,
    ]);
    Db::name('marketing_strategy_scenario')->insert([
        'strategy_id' => $fixture['strategy_id'],
        'scenario' => 1,
        'store_id' => 10001,
        'create_time' => $now,
    ]);
    if (Db::query("SHOW TABLES LIKE '" . addslashes(config('database.prefix') . 'marketing_strategy_time_range') . "'")) {
        Db::name('marketing_strategy_time_range')->insert([
            'strategy_id' => $fixture['strategy_id'],
            'start_time' => '10:01:00',
            'end_time' => '16:00:00',
            'strategy_type' => null,
            'strategy_value' => null,
            'sort' => 2,
            'store_id' => 10001,
            'create_time' => $now,
        ]);
    }

    Db::name('meal_order')
        ->where('msgid', $payload['msgid'])
        ->update([
            'is_delete' => 1,
            'update_time' => $now,
        ]);

    $consumeDate = date('Ymd', strtotime($payload['create_time']));
    $todayDate = date('Ymd');
    codex_delete_redis_keys([
        'consume_orderpay_' . $payload['msgid'],
        'consume_orderpay_staff_' . $fixture['staff_uuid'] . $payload['equipment_code'],
        'consume_orderpay_staff_' . $fixture['staff_uuid'] . $fixture['equipment_id'],
        'zhct:mqtt:consume:card:' . $payload['card_id'],
        'zhct:mqtt:consume:lock:' . $payload['card_id'],
        'zhct:mqtt:consume:msg:' . $payload['msgid'],
        'zhct:consume:' . $consumeDate . ':order:' . $payload['msgid'],
        'zhct:consume:' . $todayDate . ':order:' . $payload['msgid'],
        'zhct:consume:' . $todayDate . ':card:' . $payload['card_id'],
    ]);

    $redis = getRedis();
    if ($redis instanceof Redis) {
        $snapshot = [
            'card_id' => $payload['card_id'],
            'staff_uuid' => $fixture['staff_uuid'],
            'staff_name' => '刘平(LD)',
            'ai_user_id' => 23,
            'cash_balance' => '100.00',
            'subsidies' => [],
            'updated_at' => $now,
        ];
        $redis->setex('zhct:mqtt:consume:card:' . $payload['card_id'], 300, json_encode($snapshot, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
    }

    echo 'fixture_restaurant_id=' . $fixture['restaurant_id'] . PHP_EOL;
    echo 'fixture_equipment_id=' . $fixture['equipment_id'] . PHP_EOL;
    echo 'fixture_user_id=' . $fixture['user_id'] . PHP_EOL;
    echo 'fixture_staff_uuid=' . $fixture['staff_uuid'] . PHP_EOL;
    echo 'fixture_strategy_id=' . $fixture['strategy_id'] . PHP_EOL;
    echo 'fixture_department_uuid=' . $departmentUuid . PHP_EOL;
    echo 'fixture_card_id=' . $payload['card_id'] . PHP_EOL;
    echo 'fixture_equipment_code=' . $payload['equipment_code'] . PHP_EOL;
    echo 'calling=MqttServer::dispatch(action=consume)' . PHP_EOL;

    App::$trace_id = 'codex_' . substr(md5($marker), 0, 12);
    if (getenv('REPRO_ASYNC_FIRST_ONLY')) {
        $service = new \app\api\service\Consume();
        $params = [
            'staff_uuid' => $payload['staff_uuid'] ?? '',
            'paycode' => $payload['paycode'] ?? '',
            'card_id' => $payload['card_id'] ?? '',
            'equipment_code' => $payload['equipment_code'] ?? '',
            'money' => $payload['money'] ?? 0,
            'dishes' => $payload['dishes'] ?? [],
            'create_time' => $payload['create_time'] ?? date('Y-m-d H:i:s'),
            'msgid' => $payload['msgid'],
            'pay_type' => 20,
            'order_source' => \app\common\enum\order\OrderSource::CONSUMEORDER,
        ];
        $params['restaurant_id'] = codex_call_private($service, 'resolveOrderRestaurantId', [$params]);
        $consumeTime = date('Y-m-d H:i:s', strtotime((string)$params['create_time']));
        $params = codex_call_private($service, 'normalizeOrderMealParams', [$params, $consumeTime]);
        $snapshot = codex_call_private($service, 'getAsyncConsumeSnapshot', [$redis, $payload['card_id']]);
        echo 'calling=Consume::handleAsyncSnapshotPayment(async-first-only)' . PHP_EOL;
        echo 'async_snapshot=' . json_encode($snapshot, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
        codex_call_private($service, 'handleAsyncSnapshotPayment', [
            $redis,
            $snapshot,
            $params,
            $payload['card_id'],
            (float)$payload['money'],
            $consumeTime,
            $payload['msgid'],
            1,
            \app\common\enum\order\OrderSource::CONSUMEORDER,
        ]);
    }

    $server = new MqttServer();
    $method = new ReflectionMethod($server, 'dispatch');
    $method->setAccessible(true);
    $result = $method->invoke($server, $payload, new Output());

    echo 'UNEXPECTED_OK result=' . json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
    exit(1);
} catch (Throwable $e) {
    echo 'EXPECTED_EXCEPTION_CLASS=' . get_class($e) . PHP_EOL;
    echo 'EXPECTED_EXCEPTION_MESSAGE=' . $e->getMessage() . PHP_EOL;
    exit(strpos($e->getMessage(), 'mixed named and positional parameters') !== false ? 0 : 2);
}
