<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Models\Order;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Http;
use App\Helpers\BalanceHelper;
use App\Helpers\WebhookHelper;
use App\Models\User;

class SmscodeFallbackWorker extends Command
{
    protected $signature = 'smscode:fallback';
    protected $description = 'Fallback worker SMSCode (21 menit safety)';

    public function handle()
    {
        $this->info("SMSCode fallback worker running...");

        while (true) {

            // =========================
            // 🚀 STEP 1: SYNC PROVIDER
            // =========================
            try {

                $res = Http::withToken(config('services.smscode.api_key'))
                    ->timeout(10)
                    ->get('https://api.smscode.gg/v1/orders/active');

                if (!$res->ok()) {
                    Log::error("FAILED FETCH ACTIVE", ['status' => $res->status()]);
                    sleep(3);
                    continue;
                }

                $activeOrders = $res->json('data') ?? [];

                foreach ($activeOrders as $item) {

                    if (($item['status'] ?? null) !== 'OTP_RECEIVED') continue;

                    $providerId = $item['id'];

                    DB::transaction(function () use ($providerId) {

                        $o = Order::where('order_id', $providerId)
                            ->lockForUpdate()
                            ->first();

                        if (!$o || $o->finished_at || !$o->otp) return;

                        if ($o->created_at->lt(now()->subMinutes(21))) return;

                        try {
                            $finish = Http::withToken(config('services.smscode.api_key'))
                                ->timeout(5)
                                ->post('https://api.smscode.gg/v1/orders/finish', [
                                    'id' => (int) $providerId
                                ]);

                            if ($finish->ok() || $finish->status() === 409) {
                                $o->update(['finished_at' => now()]);
                            }

                        } catch (\Throwable $e) {
                            Log::error("FINISH ERROR", ['order_id' => $o->id]);
                        }
                    });
                }

            } catch (\Throwable $e) {
                Log::error("FETCH ACTIVE ERROR");
            }

            // =========================
            // 🔁 STEP 2: FALLBACK REFUND
            // =========================
            $orders = Order::where('provider', 'smscode')
                ->whereIn('status', ['PENDING', 'FAILED'])
                ->whereNull('refunded_at')
                ->where('created_at', '<=', now()->subMinutes(21))
                ->limit(10)
                ->get();

            foreach ($orders as $order) {

                try {

                   DB::transaction(function () use ($order) {

    $o = Order::lockForUpdate()->find($order->id);
    if (!$o || $o->refunded_at || $o->status === 'SUCCESS') return;
    if ($o->created_at->diffInMinutes(now()) < 21) return;

    $oldStatus = $o->status;

    $o->update([
        'status' => 'FAILED',
        'refunded_at' => now()
    ]);

    $user = User::lockForUpdate()->find($o->user_id);

    // 💰 refund (optional)
    if (env('AUTO_REFUND', true)) {
        BalanceHelper::addLog(
            $user,
            "CREDIT",
            $o->harga,
            "Refund fallback 21 menit (smscode)",
            $o->id
        );
    }

    // 🔥 webhook WAJIB jalan
    if ($oldStatus !== 'FAILED') {
        try {
            WebhookHelper::send($user, [
                'event' => 'order.failed',
                'data' => [
                    'order_id' => $o->id,
                    'status'   => 'FAILED',
                    'refund'   => (float) $o->harga,
                    'reason'   => 'timeout_21m'
                ]
            ]);
        } catch (\Throwable $e) {
            Log::error("WEBHOOK FAIL SAFE", [
                'order_id' => $o->id
            ]);
        }
    }

    Log::warning("Fallback refund #{$o->id}");
});

                } catch (\Throwable $e) {
                    Log::error("Fallback error #{$order->id}");
                }
            }

            sleep(5); // jangan kecilin lagi
        }
    }
}