<?php

namespace App\Http\Controllers\SelfPaced\Public;

use App\Http\Controllers\Controller;
use App\Models\Organization;
use App\Models\SelfPaced\Course;
use App\Models\SelfPaced\CourseCategory;
use App\Models\SelfPaced\Enrollment;
use App\Models\User;
use App\Services\SelfPacedService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Spatie\Permission\Models\Role;

class PublicController extends Controller
{
    public function __construct(protected SelfPacedService $selfPacedService)
    {
        // Public routes — no auth middleware here; individual methods enforce as needed
    }

    // =========================================================================
    // LANDING PAGE
    // =========================================================================

    /**
     * Public landing page — lists all published courses.
     * Requirement 13.1, 13.5, 13.6, 13.7
     */
    public function index(Request $request)
    {
        $organization = Organization::first();
        $categories   = CourseCategory::ordered()->withCount(['courses' => fn ($q) => $q->where('status', 'published')])->get();

        $query = Course::published()->with('category');

        if ($search = $request->get('search')) {
            $query->where(function ($q) use ($search) {
                $q->where('title', 'like', "%{$search}%")
                  ->orWhere('description', 'like', "%{$search}%");
            });
        }

        if ($categoryId = $request->get('category_id')) {
            $query->where('category_id', $categoryId);
        }

        $courses = $query->orderBy('title')->paginate(12)->withQueryString();

        if ($request->ajax()) {
            return response()->json([
                'html' => view('self-paced.public.partials.course-cards', compact('courses'))->render(),
            ]);
        }

        return view('self-paced.public.index', compact('courses', 'categories', 'organization'));
    }

    /**
     * Show a single published course detail page.
     * Requirement 13.1
     */
    public function show(Course $course)
    {
        abort_unless($course->isPublished(), 404);

        $organization = Organization::first();
        $course->load(['category', 'instructor', 'topics']);
        $course->loadCount(['enrollments', 'examQuestions']);

        $userEnrollment = null;
        if (Auth::check()) {
            $userEnrollment = Enrollment::where('user_id', Auth::id())
                ->where('course_id', $course->id)
                ->first();
        }

        return view('self-paced.public.show', compact('course', 'organization', 'userEnrollment'));
    }

    // =========================================================================
    // REGISTRATION — Step 1: Personal Details
    // =========================================================================

    /**
     * Show the registration form for a course.
     * Requirement 5.1
     */
    public function register(Course $course)
    {
        abort_unless($course->isPublished(), 404);

        // If already logged in and enrolled, redirect to learner portal
        if (Auth::check()) {
            $enrollment = Enrollment::where('user_id', Auth::id())
                ->where('course_id', $course->id)
                ->whereIn('status', ['active', 'completed'])
                ->first();

            if ($enrollment) {
                return redirect()->route('self-paced.learn.overview', $course)
                    ->with('info', 'You are already enrolled in this course.');
            }
        }

        $organization = Organization::first();

        return view('self-paced.public.register', compact('course', 'organization'));
    }

    /**
     * Handle registration form submission — create user + enrollment.
     * Requirement 5.1, 5.2, 5.3, 5.8
     */
    public function submitRegistration(Request $request, Course $course)
    {
        abort_unless($course->isPublished(), 404);

        $rules = [
            'name'             => 'required|string|max:191',
            'email'            => 'required|email|max:191',
            'phone'            => 'nullable|string|max:20',
            'password'         => 'required|string|min:8|confirmed',
            'payment_method'   => 'nullable|in:mobile,card',
        ];

        // Conditional payment validation for paid courses
        if (!$course->isFree()) {
            $paymentMethod = $request->input('payment_method', 'mobile');
            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 {
                // payment-method-toggle submits 'phone_number'
                $rules['phone_number'] = 'required|string|max:20';
            }
        }

        $validator = Validator::make($request->all(), $rules);

        if ($validator->fails()) {
            return back()->withErrors($validator)->withInput();
        }

        // Find or create user
        $user = User::where('email', $request->input('email'))->first();

        if (!$user) {
            $user = User::create([
                'name'     => $request->input('name'),
                'email'    => $request->input('email'),
                'username' => User::generateUsername($request->input('email')),
                'password' => Hash::make($request->input('password')),
            ]);

            // Assign Trainees role
            $traineeRole = Role::where('name', 'Trainees')->first();
            if ($traineeRole) {
                $user->assignRole($traineeRole);
            }
        }

        // Check for existing active enrollment
        $existing = Enrollment::where('user_id', $user->id)
            ->where('course_id', $course->id)
            ->whereIn('status', ['active', 'completed', 'pending_payment'])
            ->first();

        if ($existing) {
            Auth::login($user);
            if ($existing->canAccess()) {
                return redirect()->route('self-paced.learn.overview', $course)
                    ->with('info', 'You are already enrolled in this course.');
            }
            // Pending payment — go to payment step
            return redirect()->route('self-paced.public.payment', [$course, $existing]);
        }

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

        // Create enrollment
        try {
            $result = $this->selfPacedService->createEnrollment(
                userId: $user->id,
                course: $course,
                phoneNumber: $request->input('phone_number', ''),
                createdBy: $user->id,
                paymentMethod: $paymentMethod,
                cardNumber: $request->input('card_number'),
                cardExpiry: $request->input('card_expiry'),
                cardCvv: $request->input('card_cvv'),
            );
        } catch (\RuntimeException $e) {
            return back()->withErrors(['email' => $e->getMessage()])->withInput();
        }

        Auth::login($user);

        $enrollment = $result['enrollment'];

        // Free course — go straight to learner portal
        if ($course->isFree()) {
            return redirect()->route('self-paced.learn.overview', $course)
                ->with('success', 'Enrollment successful! Welcome to the course.');
        }

        // Paid course — go to payment confirmation step
        return redirect()->route('self-paced.public.payment', [$course, $enrollment]);
    }

    // =========================================================================
    // PAYMENT — Step 2 & 3
    // =========================================================================

    /**
     * Show payment status / confirmation page.
     * Requirement 5.3, 5.4, 5.5
     */
    public function payment(Course $course, Enrollment $enrollment)
    {
        abort_unless(Auth::check(), 401);
        abort_unless($enrollment->user_id === Auth::id(), 403);
        abort_unless($enrollment->course_id === $course->id, 404);

        $organization = Organization::first();

        // Already active — redirect to portal
        if ($enrollment->canAccess()) {
            return redirect()->route('self-paced.learn.overview', $course)
                ->with('success', 'Payment confirmed! You can now start learning.');
        }

        return view('self-paced.public.payment', compact('course', 'enrollment', 'organization'));
    }

    /**
     * Poll payment status (AJAX GET).
     * Requirement 5.4, 5.5
     */
    public function paymentStatus(Course $course, Enrollment $enrollment)
    {
        abort_unless(Auth::check(), 401);
        abort_unless($enrollment->user_id === Auth::id(), 403);

        $enrollment = $this->selfPacedService->checkPaymentStatus($enrollment);

        return response()->json([
            'status'       => $enrollment->status,
            'can_access'   => $enrollment->canAccess(),
            'redirect_url' => $enrollment->canAccess()
                ? route('self-paced.learn.overview', $course)
                : null,
        ]);
    }

    /**
     * Initialize Paystack payment for enrollment fee.
     * Called after enrollment created with pending payment status.
     *
     * @param Course $course
     * @param Enrollment $enrollment
     * @return \Illuminate\Http\JsonResponse
     *
     * Requirements: 1.3, 1.4
     */
    public function initPayment(Course $course, Enrollment $enrollment)
    {
        abort_unless(Auth::check(), 401);
        abort_unless($enrollment->user_id === Auth::id(), 403);

        // For cash payment
        if (request()->input('method') === 'cash') {
            return response()->json(['method' => 'cash']);
        }

        // For online payment, check if Paystack configured
        $config = \App\Models\SelfPaced\PaystackConfig::getActive();

        if (!$config) {
            return response()->json(['error' => 'Payment system not available'], 500);
        }

        $paystackService = app(\App\Services\PaystackService::class);

        $reference = $paystackService->generateReference('SP-ENR-');
        $totalFee = $course->getTotalEnrollmentFee();

        $inlineConfig = $paystackService->buildInlineConfig(
            publicKey: $config->public_key,
            email: Auth::user()->email,
            amount: $totalFee,
            reference: $reference,
            currency: $enrollment->currency ?? 'KES',
            metadata: [
                'enrollment_id' => $enrollment->id,
                'course_id' => $course->id,
                'fee_type' => 'enrollment',
                'breakdown' => [
                    'registration_fee' => $course->registration_fee,
                    'application_fee' => $course->application_fee,
                ],
            ]
        );

        return response()->json($inlineConfig);
    }

    /**
     * Verify Paystack payment and activate enrollment.
     *
     * @param Request $request
     * @param Course $course
     * @param Enrollment $enrollment
     * @return \Illuminate\Http\JsonResponse
     *
     * Requirements: 1.5, 1.6
     */
    public function verifyPayment(Request $request, Course $course, Enrollment $enrollment)
    {
        abort_unless(Auth::check(), 401);
        abort_unless($enrollment->user_id === Auth::id(), 403);

        $reference = $request->input('reference');
        $config = \App\Models\SelfPaced\PaystackConfig::getActive();

        if (!$config) {
            return response()->json(['error' => 'Payment system error'], 500);
        }

        $paystackService = app(\App\Services\PaystackService::class);

        // Verify transaction with Paystack
        $result = $paystackService->verifyTransaction(
            $reference,
            $config->secret_key
        );

        if ($result['status'] !== 'success') {
            return response()->json(['error' => 'Payment verification failed'], 400);
        }

        // Activate enrollment
        $enrollment->update([
            'status' => 'active',
            'payment_reference' => $reference,
            'registration_fee_paid' => $enrollment->course->registration_fee,
            'application_fee_paid' => $enrollment->course->application_fee,
            'amount_paid' => $enrollment->course->getTotalEnrollmentFee(),
        ]);

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

    /**
     * Submit cash payment proof for enrollment fee.
     *
     * @param \App\Http\Requests\SelfPaced\StorePaymentProofRequest $request
     * @param Course $course
     * @param Enrollment $enrollment
     * @return \Illuminate\Http\RedirectResponse
     *
     * Requirements: 1.9
     */
    public function submitPaymentProof($request, Course $course, Enrollment $enrollment)
    {
        abort_unless(Auth::check(), 401);
        abort_unless($enrollment->user_id === Auth::id(), 403);

        $paymentProofService = app(\App\Services\PaymentProofService::class);

        try {
            $proof = $paymentProofService->storeProof(
                $enrollment,
                $request->file('file'),
                $request->input('proof_type'),
                'enrollment',
                $enrollment->course->getTotalEnrollmentFee(),
                $enrollment->currency ?? 'KES'
            );

            $enrollment->update(['status' => 'pending_verification']);

            return redirect()->route('self-paced.public.payment', [$course, $enrollment])
                ->with('success', 'Payment proof submitted. Awaiting manager verification.');
        } catch (\Exception $e) {
            return back()->with('error', $e->getMessage());
        }
    }

