<?php

namespace App\Console\Commands;

use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\Booking;
use App\Models\LarkPushed;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class LarkPushBookingModuleCommand extends Command
{
    protected $signature   = 'lark:push-booking-module {--limit=10}';
    protected $description = 'Send booking records to a Lark webhook, one by one.';

    public function handle(): int
    {
        $module = 'Booking';
        $webhookId = config('services.lark.booking_webhook_id', env('LARK_BOOKING1_WEBHOOK_ID'));
        if (!$webhookId) {
            $this->error('[Lark ' . $module . '] Missing LARK_BOOKING1_WEBHOOK_ID');
            return self::FAILURE;
        }

        if (!app()->isProduction()) {
            $this->info('[Lark ' . $module . '] Skipped in non-production.');
            return self::SUCCESS;
        }

        $limit   = (int) $this->option('limit');
        $url     = "https://hfbbr1an7s0.sg.larksuite.com/base/automation/webhook/event/{$webhookId}";
        $statusM = ApprovalStatus::APPROVAL_STATUS_ID;

        $bookings = Booking::query()
            ->whereNotExists(function ($q) {
                $b = new Booking;
                $q->selectRaw(1)
                    ->from('lark_pushed')
                    ->whereColumn('lark_pushed.owner_id', 'bookings.id')
                    ->where('lark_pushed.owner_type', $b->getMorphClass())
                    ->where('lark_pushed.is_success', 1);
            })
            ->limit($limit)
            ->get();

        if ($bookings->isEmpty()) {
            $this->warn('[Lark ' . $module . '] Nothing to push.');
            return self::SUCCESS;
        }

        $this->info("[Lark " . $module . "] Pushing {$bookings->count()} record(s)...");
        Log::info('[Lark ' . $module . '] Start', ['limit' => $limit, 'env' => app()->environment()]);

        foreach ($bookings as $b) {
            $payload = [
                'id'                => (string) $b->id,
                'marking'           => (string) $b->marking,
                'company_name'      => (string) $b->company->name,
                'company_reference' => (string) $b->company->reference,
                'service_name'      => (string) $b->service->name,
                'currency'          => (string) $b->fixedCurrency->short_code,
                'amount'            => $b->fix_amount,
                'status'            => (string) ($statusM[$b->status] ?? $b->status),
                'created_at'        => $b->created_at->format('Y-m-d H:i'),
                'updated_at'        => $b->updated_at->format('Y-m-d H:i'),
            ];

            try {
                $res = Http::asJson()->post($url, $payload);
                $ok  = $res->successful() && (int) data_get($res->json(), 'code', -1) === 0;

                LarkPushed::create([
                    'owner_id'   => $b->id,
                    'owner_type' => $b->getMorphClass(),
                    'is_success' => $ok ? 1 : 0,
                ]);

                if ($ok) {
                    $this->info("[Lark $module]: ✅ Sent: {$b->id} | {$b->marking}");
                } else {
                    $this->error("[Lark $module] Failed {$b->id} | {$b->marking}: {$res->status()} {$res->body()}");
                    Log::error('[Lark ' . $module . '] Push failed', [
                        'booking_id' => $b->id,
                        'status'     => $res->status(),
                        'body'       => $res->body(),
                    ]);
                }
            } catch (\Throwable $e) {
                LarkPushed::create([
                    'owner_id'   => $b->id,
                    'owner_type' => $b->getMorphClass(),
                    'is_success' => 0,
                ]);
                $this->error("[Lark $module]: ❌ Exception {$b->id} | {$b->marking}: {$e->getMessage()}");
                Log::error('[Lark ' . $module . '] Exception', [
                    'booking_id' => $b->id,
                    'exception'  => $e->getMessage(),
                ]);
            }

            sleep(1);
        }

        $this->info("[Lark " . $module . "] Finished {$bookings->count()} record(s).");
        Log::info('[Lark ' . $module . '] Finished', ['count' => $bookings->count()]);

        return self::SUCCESS;
    }
}
