<?php

namespace App\Http\Controllers;

use App\Models\GtsOrder;
use App\Models\GtsService;
use App\Models\GtsWallet;
use App\Models\GtsWalletTransaction;
use App\Models\PaymentMethod;
use App\Models\Setting;
use App\Models\SystemSetting;
use App\Services\GtsProviderApi;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
use Illuminate\View\View;

class GtsClientController extends Controller
{
    public function __construct(private readonly GtsProviderApi $providerApi)
    {
    }

    public function dashboard(Request $request): View
    {
        $this->ensureGtsTables();
        $wallet = $this->ensureWallet($request);

        return view('gts.dashboard', [
            'wallet' => $wallet,
            'orders' => $request->user()->gtsOrders()->with('service')->latest()->take(6)->get(),
            'stats' => [
                'Wallet Balance' => $wallet->balance,
                'Total Orders' => $request->user()->gtsOrders()->count(),
                'Processing' => $request->user()->gtsOrders()->whereIn('status', ['queued', 'processing', 'partial'])->count(),
                'Completed' => $request->user()->gtsOrders()->where('status', 'completed')->count(),
            ],
        ]);
    }

    public function wallet(Request $request): View
    {
        $this->ensureGtsTables();
        $wallet = $this->ensureWallet($request);

        return view('gts.wallet', [
            'wallet' => $wallet->load(['transactions' => fn ($query) => $query->with('paymentMethod')->latest()]),
            'methods' => PaymentMethod::where('status', 'active')->orderBy('name')->get(),
            'depositEnabled' => Setting::enabled('gts_deposit_enabled'),
        ]);
    }

    public function requestTopup(Request $request): RedirectResponse
    {
        $this->ensureGtsTables();

        $data = $request->validate([
            'amount' => ['required', 'numeric', 'min:1'],
            'payment_method_id' => ['required', 'exists:payment_methods,id'],
            'reference' => ['required', 'string', 'max:255'],
            'sender_account' => ['nullable', 'string', 'max:255'],
            'proof_path' => ['required', 'file', 'mimes:'.SystemSetting::uploadExtensions().',jpg,jpeg,png,webp,pdf', 'max:'.SystemSetting::uploadLimitKilobytes()],
            'note' => ['nullable', 'string', 'max:1000'],
        ]);

        if (! PaymentMethod::whereKey($data['payment_method_id'])->where('status', 'active')->exists()) {
            return back()->withErrors(['payment_method_id' => 'Please select an active payment method.'])->withInput();
        }

        if ($request->hasFile('proof_path')) {
            $data['proof_path'] = $request->file('proof_path')->store('gts-deposits', 'public');
        }

        $this->ensureWallet($request)->transactions()->create($data + ['type' => 'credit', 'status' => 'pending']);

        return back()->with('status', 'Wallet top-up request submitted for admin review.');
    }

    public function services(Request $request): View
    {
        $this->ensureGtsTables();

        return view('gts.services', [
            'wallet' => $this->ensureWallet($request),
            'services' => GtsService::where('status', 'active')->orderBy('category')->orderBy('name')->get(),
            'orderCreateEnabled' => Setting::enabled('gts_order_create_enabled'),
        ]);
    }

    public function storeOrder(Request $request): RedirectResponse
    {
        $this->ensureGtsTables();

        $data = $request->validate(['gts_service_id' => ['required', 'exists:gts_services,id'], 'target_link' => ['required', 'string', 'max:500'], 'quantity' => ['required', 'integer', 'min:1']]);
        $service = GtsService::where('status', 'active')->findOrFail($data['gts_service_id']);
        if ($data['quantity'] < $service->min_quantity || $data['quantity'] > $service->max_quantity) {
            return back()->withErrors([
                'quantity' => 'Quantity must be between '.$service->min_quantity.' and '.$service->max_quantity.' for this service.',
            ])->withInput();
        }

        $charge = round(($data['quantity'] / 1000) * $service->rate_per_1000, 2);
        $order = DB::transaction(function () use ($request, $data, $service, $charge) {
            $wallet = GtsWallet::where('user_id', $request->user()->id)->lockForUpdate()->first()
                ?: GtsWallet::create(['user_id' => $request->user()->id, 'currency' => 'PKR', 'status' => 'active']);

            if ((float) $wallet->balance < $charge) {
                return null;
            }

            $wallet->balance = (float) $wallet->balance - $charge;
            $wallet->save();

            $order = GtsOrder::create($data + [
                'user_id' => $request->user()->id,
                'order_number' => 'GTS-'.Str::upper(Str::random(8)),
                'charge' => $charge,
                'status' => 'queued',
            ]);

            $wallet->transactions()->create(['type' => 'debit', 'amount' => $charge, 'reference' => $order->order_number, 'note' => $service->name, 'status' => 'completed', 'applied_at' => now()]);

            return $order;
        });

        if (! $order) {
            return back()->withErrors(['wallet' => 'Wallet balance is below this order charge. Add funds first.'])->withInput();
        }

        $this->providerApi->placeOrder($order);

        return redirect()->route('gts-client.orders')->with('status', $order->fresh()->provider_order_id ? 'GTS order placed and sent to provider.' : 'GTS order placed for admin/provider processing.');
    }

    public function orders(Request $request): View
    {
        $this->ensureGtsTables();

        return view('gts.orders', ['orders' => $request->user()->gtsOrders()->with('service')->latest()->get()]);
    }

    public function showOrder(Request $request, int $order): View
    {
        $this->ensureGtsTables();
        $order = GtsOrder::findOrFail($order);

        abort_unless($order->user_id === $request->user()->id, 404);

        return view('gts.order-show', ['order' => $order->load('service')]);
    }

    public function settings(Request $request): View
    {
        return view('gts.settings', ['user' => $request->user()]);
    }

    public function updateSettings(Request $request): RedirectResponse
    {
        $data = $request->validate(['name' => ['required', 'string', 'max:255'], 'phone' => ['nullable', 'string', 'max:50'], 'business_name' => ['nullable', 'string', 'max:255']]);
        $request->user()->update($data);

        return back()->with('status', 'GTS profile settings saved.');
    }

    private function ensureWallet(Request $request): GtsWallet
    {
        return GtsWallet::firstOrCreate(['user_id' => $request->user()->id], ['currency' => 'PKR', 'status' => 'active']);
    }

    private function ensureGtsTables(): void
    {
        foreach (['gts_services', 'gts_orders', 'gts_wallets', 'gts_wallet_transactions'] as $table) {
            if (! Schema::hasTable($table)) {
                abort(503, 'GTS tables are not migrated yet. Run php artisan migrate first.');
            }
        }
    }
}
