<?php

namespace App\Services\Manage;

use App\Enums\OwnerVerificationAction;
use App\Enums\OwnerVerificationStatus;
use App\Enums\Permission;
use App\Models\OwnerVerificationRequest;
use App\Models\ProductVariant;
use App\Models\RetailStockHistory;
use App\Models\User;
use App\Services\System\PushNotificationService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;

class RetailStockService
{
    public function __construct(
        private readonly PushNotificationService $pushNotificationService,
    ) {}

    public function transfer(int $variantId, int $quantity, User $user, ?string $notes = null): ?OwnerVerificationRequest
    {
        if ($quantity <= 0) {
            throw ValidationException::withMessages([
                'quantity' => 'Jumlah harus lebih dari 0.',
            ]);
        }

        $variant = ProductVariant::query()->with('product')->findOrFail($variantId);

        if ($variant->stock < $quantity) {
            throw ValidationException::withMessages([
                'quantity' => "Stok bagus tidak mencukupi. Stok saat ini: {$variant->stock} pcs.",
            ]);
        }

        $isOwner = $user->can(Permission::OWNER_VERIFICATIONS_VERIFY->value);

        if ($isOwner) {
            $this->executeTransfer($variant, $quantity, $user, $notes);

            return null;
        }

        $existingPending = OwnerVerificationRequest::query()
            ->where('subject_type', ProductVariant::class)
            ->where('subject_id', $variant->id)
            ->where('action', OwnerVerificationAction::RETAIL_STOCK_TRANSFER)
            ->where('status', OwnerVerificationStatus::PENDING)
            ->exists();

        if ($existingPending) {
            throw ValidationException::withMessages([
                'quantity' => 'Masih ada pengajuan transfer stok ecer yang menunggu verifikasi untuk varian ini.',
            ]);
        }

        try {
            $request = OwnerVerificationRequest::create([
                'action' => OwnerVerificationAction::RETAIL_STOCK_TRANSFER,
                'status' => OwnerVerificationStatus::PENDING,
                'subject_type' => ProductVariant::class,
                'subject_id' => $variant->id,
                'submitted_by_id' => $user->id,
                'payload' => [
                    'old' => [
                        'stock' => $variant->stock,
                        'retail_stock' => $variant->retail_stock,
                    ],
                    'new' => [
                        'quantity' => $quantity,
                        'stock' => $variant->stock - $quantity,
                        'retail_stock' => $variant->retail_stock + $quantity,
                        'notes' => $notes,
                        'variant_name' => $variant->name,
                        'product_name' => $variant->product?->name ?? '-',
                    ],
                ],
            ]);

            $productName = $variant->product?->name ?? $variant->name;

            $this->pushNotificationService->sendToRoles(
                '📦 Transfer Stok Ecer Menunggu Persetujuan Owner',
                "Pengajuan transfer {$quantity} pcs stok ecer untuk varian '{$variant->name}' menunggu verifikasi owner.",
                ['owner', 'developer'],
                route('admin.master.products.index', ['search' => $productName]),
            );

            $this->pushNotificationService->sendToUser(
                '📤 Pengajuan Transfer Terkirim',
                "Pengajuan transfer {$quantity} pcs stok ecer untuk varian '{$variant->name}' telah dikirim dan menunggu verifikasi owner.",
                $user->id,
                route('admin.master.products.index', ['search' => $productName]),
            );

            return $request;
        } catch (ValidationException $e) {
            throw $e;
        } catch (\Throwable $e) {
            Log::error('Gagal mengajukan transfer stok ecer: '.$e->getMessage(), [
                'trace' => $e->getTraceAsString(),
            ]);

            throw ValidationException::withMessages([
                'system' => 'Terjadi kesalahan pada server. Silakan laporkan masalah ini ke pihak terkait.',
            ]);
        }
    }

    public function applyRetailStockTransfer(OwnerVerificationRequest $request): void
    {
        $payload = $request->payload ?? [];
        $newData = $payload['new'] ?? [];
        $quantity = (int) ($newData['quantity'] ?? 0);

        if ($quantity <= 0) {
            return;
        }

        $variant = ProductVariant::query()->find($request->subject_id);

        if (! $variant) {
            return;
        }

        $this->executeTransfer($variant, $quantity, $request->submittedBy, $newData['notes'] ?? null);
    }

    private function executeTransfer(ProductVariant $variant, int $quantity, User $user, ?string $notes = null): void
    {
        DB::transaction(function () use ($variant, $quantity, $user, $notes): void {
            $variant = ProductVariant::query()
                ->whereKey($variant->id)
                ->lockForUpdate()
                ->firstOrFail();

            $stockBefore = $variant->stock;
            $retailStockBefore = $variant->retail_stock;

            $variant->decrement('stock', $quantity);
            $variant->increment('retail_stock', $quantity);

            RetailStockHistory::create([
                'product_variant_id' => $variant->id,
                'user_id' => $user->id,
                'quantity' => $quantity,
                'stock_before' => $stockBefore,
                'retail_stock_before' => $retailStockBefore,
                'stock_after' => $stockBefore - $quantity,
                'retail_stock_after' => $retailStockBefore + $quantity,
                'notes' => $notes,
                'created_at' => now(),
            ]);
        });
    }

    public function rejectRetailStockTransfer(OwnerVerificationRequest $request): void
    {
        // No-op: nothing was changed yet, so nothing to rollback.
    }
}
