<?php

namespace App\Http\Controllers\Api\Billing;

use App\Domains\Billing\Actions\CreatePaymentRequestAction;
use App\Domains\Billing\Models\PaymentRequest;
use App\Domains\Billing\Models\PaymentProvider;
use App\Domains\Billing\Models\PaymentTransaction;
use App\Domains\Orders\Models\Order;
use App\Http\Controllers\Controller;
use App\Support\PlatformSettings;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class CreateOrderPaymentRequestController extends Controller
{
    public function __invoke(Request $request, string $order, CreatePaymentRequestAction $createPaymentRequest): JsonResponse
    {
        $record = Order::query()
            ->where('tenant_id', $request->user()->tenant_id)
            ->findOrFail($order);

        $validated = $request->validate([
            'payment_method' => ['nullable', 'in:whish_api,whish_manual,cash_on_delivery'],
        ]);
        $paymentMethod = (string) ($validated['payment_method'] ?? 'whish_api');

        if ($paymentMethod === 'whish_api') {
            $provider = PaymentProvider::query()
                ->where('tenant_id', $request->user()->tenant_id)
                ->where('provider_key', (string) PlatformSettings::get('PAYMENT_DEFAULT_PROVIDER', config('payments.default_provider', 'whish')))
                ->firstOrFail();

            $credentials = is_array($provider->credentials_json) ? $provider->credentials_json : [];
            $merchantId = trim((string) ($credentials['merchant_id'] ?? ''));
            $merchantSecret = trim((string) ($credentials['merchant_secret'] ?? ''));
            if (! $provider->is_enabled || $merchantId === '' || $merchantSecret === '') {
                return response()->json([
                    'message' => 'Whish API is not configured for this company. Use manual Whish or COD.',
                ], 422);
            }

            $paymentRequest = $createPaymentRequest->execute($record, $provider, $request->user());
        } elseif ($paymentMethod === 'whish_manual') {
            $whish = PaymentProvider::query()
                ->where('tenant_id', $request->user()->tenant_id)
                ->where('provider_key', 'whish')
                ->firstOrFail();
            $credentials = is_array($whish->credentials_json) ? $whish->credentials_json : [];
            $manualWhishNumber = trim((string) ($credentials['manual_whish_number'] ?? ''));
            $enabled = (bool) ($credentials['allow_manual_whish'] ?? false);
            if (! $enabled || $manualWhishNumber === '') {
                return response()->json([
                    'message' => 'Manual Whish is not enabled for this company.',
                ], 422);
            }

            $provider = PaymentProvider::query()->firstOrCreate(
                ['tenant_id' => $request->user()->tenant_id, 'provider_key' => 'whish_manual'],
                ['display_name' => 'Whish Manual', 'is_enabled' => true, 'is_live_mode' => true]
            );

            $paymentRequest = $this->createManualPaymentRequest($record, $provider, $request->user()->id, 'MWH');
        } else {
            $whish = PaymentProvider::query()
                ->where('tenant_id', $request->user()->tenant_id)
                ->where('provider_key', 'whish')
                ->first();
            $credentials = is_array($whish?->credentials_json) ? $whish->credentials_json : [];
            $enabled = (bool) ($credentials['allow_cod'] ?? true);
            if (! $enabled) {
                return response()->json([
                    'message' => 'Cash on Delivery is disabled for this company.',
                ], 422);
            }

            $provider = PaymentProvider::query()->firstOrCreate(
                ['tenant_id' => $request->user()->tenant_id, 'provider_key' => 'cash_on_delivery'],
                ['display_name' => 'Cash on Delivery', 'is_enabled' => true, 'is_live_mode' => true]
            );

            $paymentRequest = $this->createManualPaymentRequest($record, $provider, $request->user()->id, 'COD');
        }

        return response()->json([
            'data' => [
                'id' => $paymentRequest->id,
                'status' => $paymentRequest->status,
                'amount' => $paymentRequest->amount,
                'currency_code' => $paymentRequest->currency_code,
                'external_reference' => $paymentRequest->external_reference,
                'checkout_url' => $paymentRequest->checkout_url,
                'created_at' => $paymentRequest->created_at?->toIso8601String(),
                'provider' => [
                    'display_name' => $paymentRequest->provider?->display_name,
                    'provider_key' => $paymentRequest->provider?->provider_key,
                ],
            ],
        ], 201);
    }

    private function createManualPaymentRequest(Order $order, PaymentProvider $provider, int $userId, string $prefix): PaymentRequest
    {
        $paymentRequest = PaymentRequest::query()->create([
            'tenant_id' => $order->tenant_id,
            'order_id' => $order->getKey(),
            'payment_provider_id' => $provider->getKey(),
            'status' => 'pending',
            'amount' => $order->total,
            'currency_code' => $order->currency_code,
            'external_reference' => $prefix.'-'.Str::upper(Str::random(10)),
            'checkout_url' => null,
            'created_by' => $userId,
            'expires_at' => now()->addDays(7),
        ]);

        PaymentTransaction::query()->create([
            'tenant_id' => $order->tenant_id,
            'payment_request_id' => $paymentRequest->getKey(),
            'status' => 'pending',
            'provider_reference' => $paymentRequest->external_reference,
            'amount' => $order->total,
            'currency_code' => $order->currency_code,
            'payload_json' => ['mode' => $provider->provider_key, 'manual' => true],
        ]);

        $order->update(['payment_status' => 'pending']);

        return $paymentRequest->fresh('provider');
    }
}
