<?php

namespace App\Http\Controllers\Training;

use App\Http\Controllers\Controller;
use App\Http\Requests\Training\StoreTrainingRegistrationRequest;
use App\Models\TrainingPackage;
use App\Models\TrainingRegistration;
use App\Services\RegistrationService;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\JsonResponse;

/**
 * RegistrationController
 *
 * Handles training registration management for authenticated users.
 *
 * @package App\Http\Controllers\Training
 */
class RegistrationController extends Controller
{
    /**
     * RegistrationService instance.
     *
     * @var \App\Services\RegistrationService
     */
    protected RegistrationService $registrationService;

    /**
     * Create a new RegistrationController instance.
     *
     * @param \App\Services\RegistrationService $registrationService
     */
    public function __construct(RegistrationService $registrationService)
    {
        $this->registrationService = $registrationService;
    }

    /**
     * Display a listing of all registrations.
     *
     * @return \Illuminate\View\View
     */
    public function index(): View
    {
        abort_unless(auth()->user()->can('view training registrations'), 403);

        $registrations = TrainingRegistration::with(['user', 'trainingPackage'])
            ->when(request('status'), function ($query, $status) {
                $query->where('status', $status);
            })
            ->when(request('payment_status'), function ($query, $paymentStatus) {
                $query->where('payment_status', $paymentStatus);
            })
            ->when(request('package'), function ($query, $packageId) {
                $query->where('training_package_id', $packageId);
            })
            ->when(request('search'), function ($query, $search) {
                $query->whereHas('user', function ($q) use ($search) {
                    $q->where('name', 'like', "%{$search}%")
                      ->orWhere('email', 'like', "%{$search}%");
                });
            })
            ->latest('registration_date')
            ->paginate(20);

        $packages = TrainingPackage::active()->orderBy('name')->get();
        $statistics = $this->getStatistics();

        return view('training.registrations.index', compact('registrations', 'packages', 'statistics'));
    }

    /**
     * Display current user's registrations.
     *
     * @return \Illuminate\View\View
     */
    public function myRegistrations(): View
    {
        abort_unless(auth()->user()->can('register for training'), 403);

        $registrations = TrainingRegistration::with(['trainingPackage', 'trainingPackage.sessions'])
            ->where('user_id', auth()->id())
            ->latest('registration_date')
            ->paginate(10);

        $statistics = [
            'total' => TrainingRegistration::where('user_id', auth()->id())->count(),
            'in_progress' => TrainingRegistration::where('user_id', auth()->id())->where('status', 'approved')->count(),
            'completed' => TrainingRegistration::where('user_id', auth()->id())->where('status', 'completed')->count(),
            'certificates' => TrainingRegistration::where('user_id', auth()->id())->where('certificate_issued', true)->count(),
        ];

        return view('training.registrations.my', compact('registrations', 'statistics'));
    }

    /**
     * Display pending registrations for approval.
     *
     * @return \Illuminate\View\View
     */
    public function pending(): View
    {
        abort_unless(auth()->user()->can('approve training registrations'), 403);

        $registrations = TrainingRegistration::with(['user', 'trainingPackage'])
            ->where('status', 'pending')
            ->latest('registration_date')
            ->paginate(20);

        $statistics = [
            'pending' => TrainingRegistration::where('status', 'pending')->count(),
        ];

        return view('training.registrations.pending', compact('registrations', 'statistics'));
    }

    /**
     * Show the form for creating a new registration.
     *
     * @return \Illuminate\View\View
     */
    public function create(): View
    {
        abort_unless(auth()->user()->can('register for training'), 403);

        $packages = TrainingPackage::active()
            ->public()
            ->orderBy('name')
            ->get();

        return view('training.registrations.create', compact('packages'));
    }

    /**
     * Store a newly created registration.
     *
     * @param \App\Http\Requests\Training\StoreTrainingRegistrationRequest $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(StoreTrainingRegistrationRequest $request): RedirectResponse
    {
        $validated = $request->validated();

        $package = TrainingPackage::findOrFail($validated['training_package_id']);

        if (!$package->is_public || !$package->isActive()) {
            return back()->with('error', 'This training package is not available for registration.');
        }

        try {
            $result = $this->registrationService->registerUser(
                auth()->user(),
                $package,
                [
                    'source' => 'dashboard',
                    'notes'  => $validated['notes'] ?? null,
                ]
            );

            if (!$result['success']) {
                return back()->with('error', $result['message']);
            }

            $registration = $result['registration'];

            // Process payment if required — redirect to dedicated payment page
            if ($package->requiresPayment()) {
                return redirect()
                    ->route('training.registrations.payment', $registration)
                    ->with('info', 'Registration submitted! Please complete payment to confirm your place.');
            }

            return redirect()
                ->route('training.registrations.show', $registration)
                ->with('success', 'Registration submitted successfully!');

        } catch (\Exception $e) {
            return back()
                ->withInput()
                ->with('error', 'Registration failed: ' . $e->getMessage());
        }
    }

    /**
     * Display the specified registration.
     *
     * @param \App\Models\TrainingRegistration $registration
     * @return \Illuminate\View\View
     */
    public function show(TrainingRegistration $registration): View
    {
        abort_unless(
            auth()->user()->can('view training registrations') ||
            $registration->user_id === auth()->id(),
            403
        );

        $registration->load(['user', 'trainingPackage', 'trainingPackage.sessions']);

        return view('training.registrations.show', compact('registration'));
    }

    /**
     * Approve a registration.
     *
     * @param \Illuminate\Http\Request $request
     * @param \App\Models\TrainingRegistration $registration
     * @return \Illuminate\Http\RedirectResponse
     */
    public function approve(Request $request, TrainingRegistration $registration): RedirectResponse
    {
        abort_unless(auth()->user()->can('approve training registrations'), 403);

        $validated = $request->validate([
            'approval_notes' => 'nullable|string|max:500',
        ]);

        try {
            $this->registrationService->approveRegistration(
                $registration,
                auth()->id(),
                $validated['approval_notes'] ?? null
            );

            return back()->with('success', 'Registration approved successfully!');

        } catch (\Exception $e) {
            return back()->with('error', 'Failed to approve registration: ' . $e->getMessage());
        }
    }

    /**
     * Reject a registration.
     *
     * @param \Illuminate\Http\Request $request
     * @param \App\Models\TrainingRegistration $registration
     * @return \Illuminate\Http\RedirectResponse
     */
    public function reject(Request $request, TrainingRegistration $registration): RedirectResponse
    {
        abort_unless(auth()->user()->can('approve training registrations'), 403);

        $validated = $request->validate([
            'rejection_reason' => 'required|string|max:500',
        ]);

        try {
            $this->registrationService->rejectRegistration(
                $registration,
                auth()->id(),
                $validated['rejection_reason']
            );

            return back()->with('success', 'Registration rejected.');

        } catch (\Exception $e) {
            return back()->with('error', 'Failed to reject registration: ' . $e->getMessage());
        }
    }

    /**
     * Cancel a registration.
     *
     * @param \Illuminate\Http\Request $request
     * @param \App\Models\TrainingRegistration $registration
     * @return \Illuminate\Http\RedirectResponse
     */
    public function cancel(Request $request, TrainingRegistration $registration): RedirectResponse
    {
        abort_unless(
            auth()->user()->can('cancel training registrations') ||
            $registration->user_id === auth()->id(),
            403
        );

        $validated = $request->validate([
            'cancellation_reason' => 'nullable|string|max:500',
        ]);

        try {
            $this->registrationService->cancelRegistration(
                $registration,
                $validated['cancellation_reason'] ?? 'Cancelled by user'
            );

            return back()->with('success', 'Registration cancelled successfully.');

        } catch (\Exception $e) {
            return back()->with('error', 'Failed to cancel registration: ' . $e->getMessage());
        }
    }

    /**
     * Mark a registration as completed.
     *
     * @param \Illuminate\Http\Request $request
     * @param \App\Models\TrainingRegistration $registration
     * @return \Illuminate\Http\RedirectResponse
     */
    public function complete(Request $request, TrainingRegistration $registration): RedirectResponse
    {
        abort_unless(auth()->user()->can('complete training registrations'), 403);

        $validated = $request->validate([
            'attendance_percentage' => 'required|numeric|min:0|max:100',
            'score' => 'nullable|numeric|min:0|max:100',
            'passed' => 'nullable|boolean',
        ]);

        try {
            $this->registrationService->completeRegistration(
                $registration,
                $validated['attendance_percentage'],
                $validated['score'] ?? null,
                $validated['passed'] ?? null
            );

            return back()->with('success', 'Registration marked as completed.');

        } catch (\Exception $e) {
            return back()->with('error', 'Failed to complete registration: ' . $e->getMessage());
        }
    }

    /**
     * Show payment page for a registration.
     *
     * @param \App\Models\TrainingRegistration $registration
     * @return \Illuminate\View\View
     */
    public function payment(TrainingRegistration $registration): View
    {
        abort_unless(
            $registration->user_id === auth()->id() ||
            auth()->user()->can('view training payments'),
            403
        );

        $registration->load(['user', 'trainingPackage']);

        return view('training.registrations.payment', compact('registration'));
    }

    /**
     * Process payment for a registration.
     *
     * @param \Illuminate\Http\Request $request
     * @param \App\Models\TrainingRegistration $registration
     * @return \Illuminate\Http\RedirectResponse
     */
    public function processPayment(Request $request, TrainingRegistration $registration): RedirectResponse
    {
        abort_unless($registration->user_id === auth()->id(), 403);

        $paymentMethod = $request->input('payment_method', 'mobile');

        $rules = ['payment_method' => 'nullable|in:mobile,card'];
        if ($paymentMethod === 'card') {
            $rules['card_number'] = 'required|string';
            $rules['card_expiry'] = ['required', 'regex:/^(0[1-9]|1[0-2])\/\d{2}$/'];
            $rules['card_cvv']    = 'required|digits_between:3,4';
        } else {
            // The payment-method-toggle component submits 'phone_number'
            $rules['phone_number'] = 'required|string|max:20';
        }

        $validated = $request->validate($rules);

        try {
            $result = $this->registrationService->processPayment(
                registration: $registration,
                phoneNumber: $validated['phone_number'] ?? '',
                paymentMethod: $paymentMethod,
                cardNumber: $validated['card_number'] ?? null,
                cardExpiry: $validated['card_expiry'] ?? null,
                cardCvv: $validated['card_cvv'] ?? null,
            );

            if ($result['success']) {
                return back()->with('info', $result['message']);
            }

            return back()->with('error', $result['message']);

        } catch (\Exception $e) {
            return back()->with('error', 'Payment failed: ' . $e->getMessage());
        }
    }

    /**
     * Check payment status (AJAX).
     *
     * @param \App\Models\TrainingRegistration $registration
     * @return \Illuminate\Http\JsonResponse
     */
    public function paymentStatus(TrainingRegistration $registration): JsonResponse
    {
        return response()->json([
            'status' => $registration->payment_status,
            'amount_paid' => $registration->amount_paid,
            'payment_reference' => $registration->payment_reference,
        ]);
    }

    /**
     * API endpoint for payment status check.
     *
     * @param \App\Models\TrainingRegistration $registration
     * @return \Illuminate\Http\JsonResponse
     */
    public function apiPaymentStatus(TrainingRegistration $registration): JsonResponse
    {
        return response()->json([
            'status' => $registration->payment_status,
            'amount_paid' => $registration->amount_paid,
            'payment_reference' => $registration->payment_reference,
        ]);
    }

    /**
     * Get registration statistics.
     *
     * @return array
     */
    protected function getStatistics(): array
    {
        return [
            'total' => TrainingRegistration::count(),
            'pending' => TrainingRegistration::where('status', 'pending')->count(),
            'approved' => TrainingRegistration::where('status', 'approved')->count(),
            'completed' => TrainingRegistration::where('status', 'completed')->count(),
            'rejected' => TrainingRegistration::where('status', 'rejected')->count(),
            'cancelled' => TrainingRegistration::where('status', 'cancelled')->count(),
        ];
    }
}
