<?php

namespace App\Http\Controllers;

use App\Models\Central\PlatformSetting;
use App\Models\Central\Subscription;
use App\Tenancy\TenantManager;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

/**
 * Payment flow:
 *  - GET  /billing                      → tenant invoices list (auth required)
 *  - POST /pay/{subscription}           → start checkout (Stripe/PayPal/Bank)
 *  - GET  /pay/{subscription}/success   → marked paid via webhook in real flow
 *  - GET  /pay/{subscription}/cancel    → user aborted
 *  - POST /payments/stripe/webhook      → Stripe → mark paid
 *  - POST /payments/paypal/webhook      → PayPal → mark paid
 */
class PaymentController
{
    public function billing(Request $request)
    {
        $tenant = app(TenantManager::class)->current();
        if (! $tenant) abort(404);

        $user = $request->user();
        if (! $user) {
            return redirect('/app/login');
        }

        $invoices = Subscription::where('company_id', $tenant->id)
            ->latest('period_end')
            ->limit(20)
            ->get();

        $methods = $this->availableMethods();
        $bank = PlatformSetting::get('payments.bank', []);
        $legal = PlatformSetting::get('payments.company_legal', []);

        return view('site.billing', [
            'tenant' => $tenant,
            'invoices' => $invoices,
            'methods' => $methods,
            'bank' => $bank,
            'legal' => $legal,
            'themeColor' => $tenant->settings['theme_color'] ?? '#3B82F6',
        ]);
    }

    public function startCheckout(Request $request, int $subscription)
    {
        $tenant = app(TenantManager::class)->current();
        $sub = Subscription::where('company_id', $tenant?->id)->findOrFail($subscription);

        $method = $request->input('method');

        if (! in_array($method, ['stripe', 'paypal', 'paynet', 'bank'], true)) {
            abort(422, 'Method invalid');
        }

        if ($sub->status === 'paid') {
            return back()->with('error', 'Factura este deja plătită');
        }

        if ($method === 'bank') {
            // Show bank instructions page; payment is manual.
            return view('site.bank-instructions', [
                'tenant' => $tenant,
                'sub' => $sub,
                'bank' => PlatformSetting::get('payments.bank', []),
                'themeColor' => $tenant->settings['theme_color'] ?? '#3B82F6',
            ]);
        }

        if ($method === 'stripe') {
            return $this->startStripe($sub);
        }

        if ($method === 'paypal') {
            return $this->startPaypal($sub);
        }

        if ($method === 'paynet') {
            return $this->startPaynet($sub);
        }
    }

    private function startStripe(Subscription $sub)
    {
        $stripe = PlatformSetting::get('payments.stripe', []);
        if (empty($stripe['enabled']) || empty($stripe['secret_key'])) {
            return back()->with('error', 'Stripe nu este configurat. Contactează operatorul.');
        }

        // Real implementation requires `stripe/stripe-php` package. Here we
        // produce a stub that explains the flow; in prod, replace with:
        //   $session = \Stripe\Checkout\Session::create([...]);
        //   return redirect($session->url);
        return view('site.checkout-stub', [
            'gateway' => 'Stripe',
            'sub' => $sub,
            'note' => 'Pentru a activa Stripe Checkout, instalează `composer require stripe/stripe-php` și activează în /admin/payment-settings.',
        ]);
    }

    private function startPaypal(Subscription $sub)
    {
        $paypal = PlatformSetting::get('payments.paypal', []);
        if (empty($paypal['enabled']) || empty($paypal['client_id'])) {
            return back()->with('error', 'PayPal nu este configurat.');
        }

        return view('site.checkout-stub', [
            'gateway' => 'PayPal',
            'sub' => $sub,
            'note' => 'Pentru a activa PayPal, instalează `composer require srmklive/paypal` și activează în /admin/payment-settings.',
        ]);
    }

    private function startPaynet(Subscription $sub)
    {
        $paynet = PlatformSetting::get('payments.paynet', []);
        if (empty($paynet['enabled']) || empty($paynet['merchant_code']) || empty($paynet['secret'])) {
            return back()->with('error', 'Paynet nu este configurat. Contactează operatorul.');
        }

        $base = $paynet['mode'] === 'live'
            ? 'https://paynet.md/payment'
            : 'https://test.paynet.md/payment';

        // Real flow: build POST form to Paynet with HMAC-SHA256 signature.
        // Stubbed for now until merchant credentials are set + tested.
        return view('site.checkout-stub', [
            'gateway' => 'Paynet (' . strtoupper($paynet['mode']) . ')',
            'sub' => $sub,
            'note' => "În prod: redirect către {$base} cu form ascuns (Merchant_Code, Service_ID, Order_ID={$sub->invoice_number}, Amount, Currency, Notify_URL, Return_URL, semnătură HMAC-SHA256). La success, webhook semnat verifică plata și marchează factura.",
        ]);
    }

    public function success(int $subscription)
    {
        $sub = Subscription::findOrFail($subscription);
        return view('site.payment-success', ['sub' => $sub]);
    }

    public function cancel(int $subscription)
    {
        return view('site.payment-cancel');
    }

    public function stripeWebhook(Request $request)
    {
        $stripe = PlatformSetting::get('payments.stripe', []);
        $secret = $stripe['webhook_secret'] ?? null;

        if (! $secret) {
            Log::warning('Stripe webhook hit but no secret configured');
            return response()->json(['ok' => false], 400);
        }

        // Real impl: \Stripe\Webhook::constructEvent($payload, $sig, $secret)
        // Mock: trust the body shape for stub mode.
        $payload = $request->json()->all();
        $event = $payload['type'] ?? null;

        if ($event === 'checkout.session.completed') {
            $subId = $payload['data']['object']['metadata']['subscription_id'] ?? null;
            if ($subId && $sub = Subscription::find($subId)) {
                $this->markPaid($sub, 'stripe_card', $payload['data']['object']['id'] ?? null);
            }
        }

        return response()->json(['ok' => true]);
    }

    public function paypalWebhook(Request $request)
    {
        // Real impl: verify signature with PayPal
        $payload = $request->json()->all();
        $event = $payload['event_type'] ?? null;

        if ($event === 'CHECKOUT.ORDER.APPROVED' || $event === 'PAYMENT.CAPTURE.COMPLETED') {
            $subId = $payload['resource']['custom_id'] ?? null;
            if ($subId && $sub = Subscription::find($subId)) {
                $this->markPaid($sub, 'paypal', $payload['resource']['id'] ?? null);
            }
        }

        return response()->json(['ok' => true]);
    }

    public function paynetWebhook(Request $request)
    {
        $paynet = PlatformSetting::get('payments.paynet', []);
        $secret = $paynet['secret'] ?? null;

        if (! $secret) {
            Log::warning('Paynet webhook hit but no secret configured');
            return response('error', 400);
        }

        // Paynet sends form-encoded notification. Verify HMAC-SHA256 signature
        // computed over the canonical concatenated payload.
        $orderId = $request->input('Order_ID');     // matches our invoice_number
        $status = $request->input('Status');         // OK / FAIL
        $amount = $request->input('Amount');
        $signature = $request->input('Signature');

        // Canonical signature payload (Merchant_Code|Order_ID|Amount|Status).
        $canonical = ($paynet['merchant_code'] ?? '') . '|' . $orderId . '|' . $amount . '|' . $status;
        $expected = hash_hmac('sha256', $canonical, $secret);

        if (! hash_equals($expected, (string) $signature)) {
            Log::warning('Paynet webhook signature mismatch', ['order' => $orderId]);
            return response('invalid signature', 400);
        }

        if ($status !== 'OK') {
            return response('ok', 200);
        }

        $sub = Subscription::where('invoice_number', $orderId)->first();
        if ($sub) {
            $this->markPaid($sub, 'paynet', $request->input('Reference_ID'));
        }

        return response('ok', 200);
    }

    private function markPaid(Subscription $sub, string $method, ?string $reference): void
    {
        if ($sub->status === 'paid') return;

        $sub->update([
            'status' => 'paid',
            'paid_at' => now(),
            'payment_method' => $method,
            'reference' => $reference,
        ]);

        // Extend company subscription
        $sub->company?->update([
            'status' => 'active',
            'active_until' => $sub->period_end,
        ]);
    }

    private function availableMethods(): array
    {
        $stripe = PlatformSetting::get('payments.stripe', []);
        $paypal = PlatformSetting::get('payments.paypal', []);
        $paynet = PlatformSetting::get('payments.paynet', []);
        $bank = PlatformSetting::get('payments.bank', []);

        return [
            'stripe' => ! empty($stripe['enabled']) && ! empty($stripe['publishable_key']),
            'paypal' => ! empty($paypal['enabled']) && ! empty($paypal['client_id']),
            'paynet' => ! empty($paynet['enabled']) && ! empty($paynet['merchant_code']),
            'bank' => ! empty($bank['enabled']) && ! empty($bank['iban']),
        ];
    }
}
