<?php

namespace App\Jobs;

use App\Events\ProductProvisioningCompleted;
use App\Events\ProductProvisioningFailed;
use App\Events\ProductProvisioningProgress;
use App\Events\ProductProvisioningStarted;
use App\Models\ClientProduct;
use App\Models\OrderItem;
use App\Services\ProductProvisioningService;
use App\Services\ProvisioningStatusService;
use Illuminate\Bus\Queueable as BusQueueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class ProcessProductCreateJob implements ShouldQueue
{
    use BusQueueable, Dispatchable, InteractsWithQueue, SerializesModels;

    public int $clientProductId;
    public ?string $provisioningId;
    public ?int $orderId;

    /**
     * Don't auto-retry - failed jobs go to failed_jobs table
     * Admin can manually retry from /admin/queue
     */
    public int $tries = 1;
    public int $timeout = 120;

    /**
     * Create a new job instance.
     *
     * @param int $clientProductId
     * @param string|null $provisioningId - Admin panel için (provisioning zaten mevcut)
     * @param int|null $orderId - Order/Payment sonrası için (provisioning otomatik oluşacak)
     */
    public function __construct(int $clientProductId, ?string $provisioningId = null, ?int $orderId = null)
    {
        $this->clientProductId = $clientProductId;
        $this->provisioningId = $provisioningId;
        $this->orderId = $orderId;
    }

    /**
     * Execute the job.
     */
    public function handle(ProvisioningStatusService $provisioningStatus, ProductProvisioningService $provisioningService): void
    {
        $clientProduct = ClientProduct::with(['product'])->find($this->clientProductId);

        if (! $clientProduct) {
            return;
        }

        // Create provisioning log for real-time tracking (Redis)
        if (! $this->provisioningId) {
            $this->provisioningId = $provisioningStatus->create(
                actionType: ProvisioningStatusService::ACTION_CREATE,
                entityType: ProvisioningStatusService::ENTITY_PRODUCT,
                entityId: $clientProduct->id,
                moduleSlug: strtolower($clientProduct->module ?? $clientProduct->product->module ?? 'unknown'),
                requestData: $this->orderId ? ['order_id' => $this->orderId] : [],
                message: $this->orderId
                    ? "Sipariş #{$this->orderId} için otomatik provisioning başlatıldı"
                    : 'Otomatik provisioning başlatıldı...'
            );
        }

        // Update with module slug
        $moduleName = strtolower($clientProduct->module ?? $clientProduct->product->module ?? 'unknown');
        $provisioningStatus->update($this->provisioningId, ['module_slug' => $moduleName]);

        event(new ProductProvisioningStarted($this->provisioningId));
        event(new ProductProvisioningProgress($this->provisioningId, 20, 'Provisioning servisi başlatılıyor...'));

        // Delegate ALL logic to ProductProvisioningService
        $result = $provisioningService->processProductProvisioning(
            $this->clientProductId,
            null,           // orderItemId - service will find it via orderId
            $this->orderId,
            $this->provisioningId  // PRC-449: snapshot'a request_data yazılabilsin
        );

        if ($result['status'] === 'success') {
            // Save response data to provisioning log
            $provisioningStatus->update($this->provisioningId, [
                'response_data' => $result['data'] ?? [],
            ]);

            event(new ProductProvisioningCompleted($this->provisioningId, $result['data'] ?? [], $this->clientProductId, 'create'));
        } else {
            // Save error to provisioning log
            $provisioningStatus->update($this->provisioningId, [
                'response_data' => ['error' => $result['message']],
            ]);

            event(new ProductProvisioningFailed(
                $this->provisioningId,
                $result['message'],
                ['client_product_id' => $this->clientProductId, 'order_id' => $this->orderId],
                $this->clientProductId,
                'create'
            ));

            // Re-throw so Laravel marks job as failed → shows in /admin/queue for retry
            if (isset($result['error']) && $result['error'] instanceof \Exception) {
                throw $result['error'];
            }
            throw new \Exception($result['message'] ?? 'Product provisioning failed');
        }
    }
}
