<?php

namespace App\Http\Controllers\Api\V1\E2E;

use App\Lottery\ErrorCode;
use App\Lottery\DrawStatus;
use App\Support\ApiResponse;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Artisan;

/**
 * E2E 辅助：期号时间/状态快进。
 *
 * 真实生产链路下"等 12 分钟后封盘"是脆的——CI 跑 e2e 不可能等。
 * 这里允许 e2e 直接 SQL 改 close_time / draw_time，模拟：
 *   - close-now: close_time 改到 1 秒前、status=closed
 *   - reopen:   status=open、重置冷却期
 *   - inspect:  返回 draw 完整时间/状态快照
 *
 * 严格仅在 LOTTERY_E2E=true 时由 E2EServiceProvider 注册。
 */
final class E2EDrawController extends Controller
{
    public function closeNow(Request $request, string $drawNo): JsonResponse
    {
        $draw = DB::table('draws')->where('draw_no', $drawNo)->first();
        if (! $draw) {
            return ApiResponse::error('draw not found', ErrorCode::NotFound->value, null, 404);
        }

        DB::table('draws')
            ->where('id', $draw->id)
            ->update([
                'status' => DrawStatus::Closed->value,
                'close_time' => now()->subSeconds(5),
                'draw_time' => now()->subSeconds(3),
            ]);

        return $this->inspectById((int) $draw->id);
    }

    /** 将冷静期结束时间改到过去，便于 tick 推进 cooldown → settling。 */
    public function finishCooldown(Request $request, string $drawNo): JsonResponse
    {
        $draw = DB::table('draws')->where('draw_no', $drawNo)->first();
        if (! $draw) {
            return ApiResponse::error('draw not found', ErrorCode::NotFound->value, null, 404);
        }

        DB::table('draws')
            ->where('id', $draw->id)
            ->update([
                'cooling_end_time' => now()->subSeconds(5),
                'draw_time' => now()->subMinutes(2),
                'close_time' => now()->subMinutes(3),
            ]);

        return $this->inspectById((int) $draw->id);
    }

    public function reopen(Request $request, string $drawNo): JsonResponse
    {
        $draw = DB::table('draws')->where('draw_no', $drawNo)->first();
        if (! $draw) {
            return ApiResponse::error('draw not found', ErrorCode::NotFound->value, null, 404);
        }

        DB::table('draws')
            ->where('id', $draw->id)
            ->update([
                'status' => DrawStatus::Open->value,
                'start_time' => now()->subMinutes(5),
                'close_time' => now()->addMinutes(20),
                'draw_time' => now()->addMinutes(21),
                'cooling_end_time' => null,
            ]);

        return $this->inspectById((int) $draw->id);
    }

    public function inspect(Request $request, string $drawNo): JsonResponse
    {
        $draw = DB::table('draws')->where('draw_no', $drawNo)->first();
        if (! $draw) {
            return ApiResponse::error('draw not found', ErrorCode::NotFound->value, null, 404);
        }

        return $this->inspectById((int) $draw->id);
    }

    /** 同步跑一次 lottery:draw-tick（不开调度）。返回该 tick 推进的 draw_no 列表。 */
    public function tick(Request $request): JsonResponse
    {
        try {
            $exit = Artisan::call('lottery:draw-tick');
        } catch (\Throwable $e) {
            return ApiResponse::error(
                'draw-tick failed: '.$e->getMessage(),
                ErrorCode::InternalError->value,
                ['trace' => array_slice(explode("\n", $e->getTraceAsString()), 0, 5)],
                500,
            );
        }

        return ApiResponse::success([
            'exit_code' => $exit,
            'output' => Artisan::output(),
        ]);
    }

    private function inspectById(int $id): JsonResponse
    {
        $d = DB::table('draws')->where('id', $id)->first();

        return ApiResponse::success([
            'id' => (int) $d->id,
            'draw_no' => $d->draw_no,
            'status' => (string) $d->status,
            'business_date' => $d->business_date,
            'start_time' => $d->start_time,
            'close_time' => $d->close_time,
            'draw_time' => $d->draw_time,
            'cooling_end_time' => $d->cooling_end_time,
            'current_result_version' => (int) $d->current_result_version,
            'settle_version' => (int) $d->settle_version,
            'is_reopened' => (bool) $d->is_reopened,
        ]);
    }
}
