<?php

namespace App\Http\Controllers;

use App\Models\CoachPlan;
use App\Models\CoachPaymentMethod;
use App\Models\PaymentReceipt;
use App\Models\CoachPlanPurchase;
use App\Models\User;
use App\Notifications\CoachNewPlanPurchase;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Inertia\Inertia;
use Inertia\Response;

class CheckoutController extends Controller
{
    /**
     * Show checkout page for a plan.
     */
    public function show(Request $request, string $slug, ?string $tierId = null): Response
    {
        $plan = CoachPlan::where('slug', $slug)
            ->where('is_active', true)
            ->where('is_public', true)
            ->with(['coach:id,name,email,avatar,bio,phone'])
            ->firstOrFail();

        if (!$plan->isAvailable()) {
            abort(404, 'Este plan no está disponible actualmente.');
        }

        // Get active payment methods for this coach
        $paymentMethods = CoachPaymentMethod::where('coach_id', $plan->coach_id)
            ->where('is_active', true)
            ->orderBy('priority')
            ->get()
            ->map(function ($method) {
                return [
                    'id' => $method->id,
                    'type' => $method->type,
                    'type_label' => $method->type_label,
                    'display_name' => $method->display_name,
                    'public_data' => $method->public_data,
                ];
            });

        // Get selected tier or default
        $selectedTier = null;
        $pricingTiers = $plan->pricing_tiers ?? [];

        // Convert tierId to int if provided
        $tierIdInt = $tierId ? (int) $tierId : null;

        if ($tierIdInt && !empty($pricingTiers)) {
            $selectedTier = collect($pricingTiers)->firstWhere('id', $tierIdInt);
        }

        if (!$selectedTier && !empty($pricingTiers)) {
            // Try to find featured tier first
            $selectedTier = collect($pricingTiers)->firstWhere('featured', true);
            // If no featured, take first
            if (!$selectedTier) {
                $selectedTier = $pricingTiers[0] ?? null;
            }
        }

        // Calculate price
        $price = $selectedTier['price'] ?? $plan->price;
        $currency = $plan->currency ?? 'USD';
        $currencySymbol = $plan->currency_symbol ?? '$';

        // Check if user already has this plan
        $existingPurchase = null;
        if ($request->user()) {
            $existingPurchase = CoachPlanPurchase::where('coach_plan_id', $plan->id)
                ->where('user_id', $request->user()->id)
                ->whereIn('status', ['pending', 'paid', 'active'])
                ->first();
        }

        return Inertia::render('Public/Checkout', [
            'plan' => [
                'id' => $plan->id,
                'name' => $plan->name,
                'slug' => $plan->slug,
                'description' => $plan->description,
                'image' => $plan->image ? asset('storage/' . $plan->image) : null,
                'duration_days' => $plan->duration_days,
                'features' => $plan->features ?? [],
                'currency' => $currency,
                'currency_symbol' => $currencySymbol,
            ],
            'coach' => [
                'id' => $plan->coach->id,
                'name' => $plan->coach->name,
                'avatar' => $plan->coach->avatar ? asset('storage/' . $plan->coach->avatar) : null,
                'phone' => $plan->coach->phone,
            ],
            'paymentMethods' => $paymentMethods,
            'selectedTier' => $selectedTier,
            'pricingTiers' => $pricingTiers,
            'price' => $price,
            'existingPurchase' => $existingPurchase,
        ]);
    }

    /**
     * Create a pending purchase and return payment instructions.
     */
    public function createPurchase(Request $request, string $slug): JsonResponse
    {
        try {
            $request->validate([
                'tier_id' => 'nullable|integer',
                'payment_method_id' => 'required|exists:coach_payment_methods,id',
                'buyer_name' => 'required|string|max:255',
                'buyer_email' => 'required|email|max:255',
                'buyer_phone' => 'nullable|string|max:50',
            ]);

            $plan = CoachPlan::where('slug', $slug)
                ->where('is_active', true)
                ->where('is_public', true)
                ->firstOrFail();

            if (!$plan->isAvailable()) {
                return response()->json(['error' => 'Este plan no está disponible'], 404);
            }

            $paymentMethod = CoachPaymentMethod::where('id', $request->payment_method_id)
                ->where('coach_id', $plan->coach_id)
                ->where('is_active', true)
                ->firstOrFail();

            // Calculate price from tier or base price
            $price = $plan->price;
            $tierName = null;
            $isRecurring = false;
            $recurringPeriod = null;

            if ($request->tier_id && !empty($plan->pricing_tiers)) {
                $tier = collect($plan->pricing_tiers)->firstWhere('id', $request->tier_id);
                if ($tier) {
                    $price = $tier['price'] ?? $plan->price;
                    $tierName = $tier['name'] ?? null;
                    $isRecurring = !empty($tier['is_recurring']);
                    $recurringPeriod = $tier['period'] ?? null;
                }
            }

            // Create purchase record
            $purchase = CoachPlanPurchase::create([
                'coach_plan_id' => $plan->id,
                'user_id' => $request->user()?->id,
                'coach_id' => $plan->coach_id,
                'status' => 'pending',
                'amount' => $price,
                'currency' => $plan->currency ?? 'USD',
                'payment_method' => $paymentMethod->type,
                'payment_method_id' => $paymentMethod->id,
                'buyer_name' => $request->buyer_name,
                'buyer_email' => $request->buyer_email,
                'buyer_phone' => $request->buyer_phone,
                'tier_name' => $tierName,
                'is_recurring' => $isRecurring,
                'recurring_period' => $recurringPeriod,
                'metadata' => [
                    'tier_id' => $request->tier_id,
                    'payment_method_type' => $paymentMethod->type,
                    'is_recurring' => $isRecurring,
                    'recurring_period' => $recurringPeriod,
                ],
            ]);

            // Notify coach about new pending purchase
            try {
                $coach = User::find($plan->coach_id);
                if ($coach) {
                    $coach->notify(new CoachNewPlanPurchase($purchase, 'new_purchase'));
                }
            } catch (\Exception $e) {
                Log::warning('Failed to notify coach about new purchase: ' . $e->getMessage());
            }

            // Return payment instructions based on method type
            $instructions = $this->getPaymentInstructions($paymentMethod, $price, $plan, $purchase);

            return response()->json([
                'purchase' => [
                    'id' => $purchase->id,
                    'reference' => $purchase->id,
                    'amount' => $price,
                    'currency' => $plan->currency ?? 'USD',
                    'currency_symbol' => $plan->currency_symbol ?? '$',
                ],
                'paymentMethod' => [
                    'type' => $paymentMethod->type,
                    'display_name' => $paymentMethod->display_name,
                ],
                'instructions' => $instructions,
            ]);
        } catch (\Illuminate\Validation\ValidationException $e) {
            return response()->json(['error' => 'Datos inválidos', 'details' => $e->errors()], 422);
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return response()->json(['error' => 'Plan o método de pago no encontrado'], 404);
        } catch (\Exception $e) {
            Log::error('Checkout error', ['error' => $e->getMessage(), 'trace' => $e->getTraceAsString()]);
            return response()->json(['error' => 'Error al procesar: ' . $e->getMessage()], 500);
        }
    }

    /**
     * Get payment instructions for a method.
     */
    private function getPaymentInstructions(CoachPaymentMethod $method, float $amount, CoachPlan $plan, CoachPlanPurchase $purchase): array
    {
        $reference = "CP-{$purchase->id}";

        switch ($method->type) {
            case 'paypal':
                $paypalMode = $method->metadata['paypal_mode'] ?? 'email';
                $instructions = [
                    'type' => 'paypal',
                    'paypal_mode' => $paypalMode,
                    'amount' => $amount,
                    'currency' => $plan->currency ?? 'USD',
                    'note' => "Pago plan: {$plan->name} - Ref: {$reference}",
                ];

                if ($paypalMode === 'paypalme' && $method->paypal_me_link) {
                    $instructions['paypal_me_link'] = "https://paypal.me/{$method->paypal_me_link}/{$amount}";
                    $instructions['paypal_me_user'] = $method->paypal_me_link;
                } elseif ($paypalMode === 'email' && $method->paypal_email) {
                    $instructions['email'] = $method->paypal_email;
                    $currency = $plan->currency ?? 'USD';
                    $itemName = urlencode("Plan {$plan->name} - Ref: {$reference}");
                    $instructions['paypal_payment_link'] = "https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=" . urlencode($method->paypal_email) . "&amount={$amount}&currency_code={$currency}&item_name={$itemName}";
                } elseif ($paypalMode === 'api') {
                    $instructions['api_mode'] = true;
                    $instructions['client_id'] = $method->paypal_client_id;
                    $instructions['sandbox'] = $method->paypal_sandbox ?? false;
                    // Generate payment link for API mode using PayPal email as fallback
                    $paypalEmail = $method->paypal_email ?? $method->paypal_client_id;
                    if ($paypalEmail) {
                        $currency = $plan->currency ?? 'USD';
                        $itemName = urlencode("Plan {$plan->name} - Ref: {$reference}");
                        $instructions['paypal_payment_link'] = "https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=" . urlencode($paypalEmail) . "&amount={$amount}&currency_code={$currency}&item_name={$itemName}";
                    }
                }

                return $instructions;

            case 'bank_dominican':
                $bankData = CoachPaymentMethod::DOMINICAN_BANKS[$method->bank_name] ?? null;
                $bankDisplayName = is_array($bankData) ? $bankData['name'] : ($bankData ?? $method->bank_name);
                return [
                    'type' => 'bank_transfer',
                    'bank_name' => $bankDisplayName,
                    'account_type' => CoachPaymentMethod::ACCOUNT_TYPES[$method->bank_account_type] ?? $method->bank_account_type,
                    'account_number' => $method->bank_account_number,
                    'holder_name' => $method->bank_holder_name,
                    'amount' => $amount,
                    'currency' => 'DOP',
                    'reference' => $reference,
                    'concept' => "Plan {$plan->name}",
                ];

            case 'bank_international':
                return [
                    'type' => 'wire_transfer',
                    'bank_name' => $method->bank_name,
                    'bank_country' => $method->bank_country,
                    'swift' => $method->bank_swift,
                    'iban' => $method->bank_iban,
                    'account_number' => $method->bank_account_number,
                    'holder_name' => $method->bank_holder_name,
                    'amount' => $amount,
                    'currency' => $method->bank_currency ?? ($plan->currency ?? 'USD'),
                    'reference' => $reference,
                ];

            case 'western_union':
                return [
                    'type' => 'western_union',
                    'receiver_name' => $method->wu_full_name,
                    'country' => $method->wu_country,
                    'city' => $method->wu_city,
                    'phone' => $method->wu_phone,
                    'amount' => $amount,
                    'currency' => $plan->currency ?? 'USD',
                    'reference' => $reference,
                ];

            default:
                return [
                    'type' => 'unknown',
                    'message' => 'Contacta al coach para instrucciones de pago.',
                ];
        }
    }

    /**
     * Upload payment receipt/proof.
     */
    public function uploadReceipt(Request $request): JsonResponse
    {
        try {
            $request->validate([
                'purchase_id' => 'required|exists:coach_plan_purchases,id',
                'receipt' => 'required|file|mimes:jpg,jpeg,png,pdf,webp|max:5120', // 5MB max
                'transaction_reference' => 'nullable|string|max:255',
                'notes' => 'nullable|string|max:1000',
            ]);

            $purchase = CoachPlanPurchase::findOrFail($request->purchase_id);

            // Verify purchase belongs to this buyer (by email or user_id) - allow if no user or matching user
            if ($request->user() && $purchase->user_id && $purchase->user_id !== $request->user()->id) {
                return response()->json(['error' => 'No autorizado para esta compra'], 403);
            }

            // Store receipt file
            $path = $request->file('receipt')->store(
                "receipts/{$purchase->coach_id}/{$purchase->id}",
                'public'
            );

            // Create receipt record
            $receipt = PaymentReceipt::create([
                'purchase_id' => $purchase->id,
                'payment_method_id' => $purchase->payment_method_id,
                'type' => $purchase->payment_method ?? 'bank_transfer',
                'receipt_image' => $path,
                'transfer_reference' => $request->transaction_reference,
                'status' => 'pending',
            ]);

            // Update purchase to record receipt upload time
            $purchase->update([
                'receipt_uploaded_at' => now(),
            ]);

            // Notify coach about receipt upload
            try {
                $coach = User::find($purchase->coach_id);
                if ($coach) {
                    $coach->notify(new CoachNewPlanPurchase($purchase, 'receipt_uploaded'));
                }
            } catch (\Exception $e) {
                Log::warning('Failed to notify coach about receipt: ' . $e->getMessage());
            }

            return response()->json([
                'message' => 'Comprobante subido correctamente. El coach revisará tu pago pronto.',
                'receipt' => [
                    'id' => $receipt->id,
                    'status' => $receipt->status,
                ],
            ]);
        } catch (\Illuminate\Validation\ValidationException $e) {
            return response()->json([
                'error' => 'Error de validación: ' . collect($e->errors())->flatten()->first(),
            ], 422);
        } catch (\Exception $e) {
            Log::error('Error uploading receipt: ' . $e->getMessage());
            return response()->json([
                'error' => 'Error al procesar el comprobante. Por favor intenta de nuevo.',
            ], 500);
        }
    }

    /**
     * Check purchase status.
     */
    public function checkStatus(Request $request, int $purchaseId): JsonResponse
    {
        $purchase = CoachPlanPurchase::findOrFail($purchaseId);

        // Verify access
        if ($purchase->buyer_email !== $request->input('email')) {
            return response()->json(['error' => 'No autorizado'], 403);
        }

        return response()->json([
            'status' => $purchase->status,
            'status_label' => $this->getStatusLabel($purchase->status),
            'created_at' => $purchase->created_at->toIso8601String(),
            'paid_at' => $purchase->paid_at?->toIso8601String(),
        ]);
    }

    /**
     * Show thank you page after receipt upload.
     */
    public function thankYou(string $slug): Response
    {
        $plan = CoachPlan::where('slug', $slug)
            ->with(['coach:id,name,email,avatar,bio'])
            ->firstOrFail();

        return Inertia::render('Public/CheckoutThankYou', [
            'plan' => [
                'name' => $plan->name,
                'slug' => $plan->slug,
                'image' => $plan->image ? asset('storage/' . $plan->image) : null,
                'duration_days' => $plan->duration_days,
            ],
            'coach' => [
                'name' => $plan->coach->name,
                'avatar' => $plan->coach->avatar ? asset('storage/' . $plan->coach->avatar) : null,
            ],
        ]);
    }

    /**
     * Get human-readable status label.
     */
    private function getStatusLabel(string $status): string
    {
        return match ($status) {
            'pending' => 'Pendiente de pago',
            'pending_review' => 'Comprobante en revisión',
            'paid' => 'Pagado',
            'active' => 'Activo',
            'expired' => 'Expirado',
            'cancelled' => 'Cancelado',
            'refunded' => 'Reembolsado',
            default => 'Desconocido',
        };
    }
}
