<?php

namespace App\Http\Controllers\Mentorship;

use App\Http\Controllers\Controller;
use App\Models\Mentorship\Application;
use App\Models\Mentorship\Programme;
use App\Services\Mentorship\RegistrationService;
use App\Http\Requests\Mentorship\ApplicationRequest;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;

class ApplicationController extends Controller
{
    protected RegistrationService $registrationService;

    public function __construct(RegistrationService $registrationService)
    {
        $this->registrationService = $registrationService;
    }

    /**
     * Display a listing of applications.
     */
    public function index(Request $request)
    {
        $user = auth()->user();

        // Mentors and Mentees can only see their own applications
        $isOwnOnly = !$user->can('view mentorship applications') && $user->can('view own mentorship applications');

        abort_unless(
            $user->can('view mentorship applications') || $user->can('view own mentorship applications'),
            403
        );

        $filters = [
            'status' => $request->get('status'),
            'programme_id' => $request->get('programme_id'),
            'role_preference' => $request->get('role_preference'),
            'payment_status' => $request->get('payment_status'),
            'search' => $request->get('search'),
            'sort_by' => $request->get('sort_by', 'created_at'),
            'sort_order' => $request->get('sort_order', 'desc'),
        ];

        if ($isOwnOnly) {
            // Scope to the authenticated user's own applications
            $applications = $this->registrationService->getApplications($filters, $user->id);
        } else {
            $applications = $this->registrationService->getApplications($filters);
        }

        $programmes = Programme::active()->orderBy('title')->get();

        return view('mentorship.applications.index', compact('applications', 'programmes', 'filters', 'isOwnOnly'));
    }

    /**
     * Display the specified application.
     */
    public function show(Application $application)
    {
        $user = auth()->user();

        // Allow if user has full view permission OR if it's their own application
        abort_unless(
            $user->can('view mentorship applications') ||
            ($user->can('view own mentorship applications') && $application->user_id === $user->id),
            403
        );

        $application->load([
            'programme',
            'category',
            'user',
            'reviewer',
            'payments',
            'mentorAssignment.mentor',
            'menteeAssignment.mentee',
        ]);

        return view('mentorship.applications.show', compact('application'));
    }

    /**
     * Show the form for editing application review.
     */
    public function edit(Application $application)
    {
        abort_unless(auth()->user()->can('review mentorship applications'), 403);

        $application->load(['programme', 'category', 'user']);

        return view('mentorship.applications.review', compact('application'));
    }

    /**
     * Mark application as under review.
     */
    public function markUnderReview(Application $application)
    {
        abort_unless(auth()->user()->can('review mentorship applications'), 403);

        try {
            $this->registrationService->markUnderReview($application, auth()->id());

            return redirect()
                ->route('mentorship.applications.show', $application)
                ->with('success', 'Application marked as under review.');
        } catch (\Exception $e) {
            return back()->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * Approve an application.
     */
    public function approve(Request $request, Application $application)
    {
        abort_unless(auth()->user()->can('approve mentorship applications'), 403);

        $request->validate([
            'review_notes' => 'nullable|string|max:2000',
        ]);

        try {
            $this->registrationService->approve(
                $application,
                auth()->id(),
                $request->review_notes
            );

            return redirect()
                ->route('mentorship.applications.show', $application)
                ->with('success', 'Application approved successfully.');
        } catch (\Exception $e) {
            return back()->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * Reject an application.
     */
    public function reject(Request $request, Application $application)
    {
        abort_unless(auth()->user()->can('reject mentorship applications'), 403);

        $request->validate([
            'rejection_reason' => 'required|string|max:1000',
            'review_notes' => 'nullable|string|max:2000',
        ]);

        try {
            $this->registrationService->reject(
                $application,
                auth()->id(),
                $request->rejection_reason,
                $request->review_notes
            );

            return redirect()
                ->route('mentorship.applications.show', $application)
                ->with('success', 'Application rejected.');
        } catch (\Exception $e) {
            return back()->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * Bulk approve applications.
     */
    public function bulkApprove(Request $request): JsonResponse
    {
        abort_unless(auth()->user()->can('approve mentorship applications'), 403);

        $request->validate([
            'application_ids' => 'required|array',
            'application_ids.*' => 'exists:mentorship_applications,id',
        ]);

        $approved = 0;
        $failed = [];

        foreach ($request->application_ids as $id) {
            $application = Application::find($id);
            
            if ($application && $application->canBeApproved()) {
                try {
                    $this->registrationService->approve($application, auth()->id());
                    $approved++;
                } catch (\Exception $e) {
                    $failed[] = ['id' => $id, 'error' => $e->getMessage()];
                }
            }
        }

        return response()->json([
            'success' => true,
            'message' => "Approved {$approved} applications.",
            'failed' => $failed,
        ]);
    }

    /**
     * Get pending applications count (AJAX).
     */
    public function pendingCount(): JsonResponse
    {
        $count = $this->registrationService->getPendingCount();

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

    /**
     * Export applications to CSV.
     */
    public function export(Request $request)
    {
        abort_unless(auth()->user()->can('view mentorship applications'), 403);

        $filters = [
            'status' => $request->get('status'),
            'programme_id' => $request->get('programme_id'),
            'role_preference' => $request->get('role_preference'),
        ];

        $applications = Application::with(['programme', 'category', 'user', 'reviewer'])
            ->when($filters['status'], fn($q) => $q->where('status', $filters['status']))
            ->when($filters['programme_id'], fn($q) => $q->where('programme_id', $filters['programme_id']))
            ->when($filters['role_preference'], fn($q) => $q->where('role_preference', $filters['role_preference']))
            ->latest()
            ->get();

        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="mentorship-applications.csv"',
        ];

        $callback = function () use ($applications) {
            $file = fopen('php://output', 'w');
            
            fputcsv($file, [
                'ID', 'Name', 'Email', 'Phone', 'Programme', 'Category',
                'Role', 'Status', 'Payment Status', 'Applied At', 'Reviewed By', 'Reviewed At'
            ]);

            foreach ($applications as $app) {
                fputcsv($file, [
                    $app->id,
                    $app->name,
                    $app->email,
                    $app->phone,
                    $app->programme->title ?? '',
                    $app->category->name ?? '',
                    $app->role_preference,
                    $app->status,
                    $app->payment_status,
                    $app->created_at->format('Y-m-d H:i:s'),
                    $app->reviewer->name ?? '',
                    $app->reviewed_at?->format('Y-m-d H:i:s') ?? '',
                ]);
            }

            fclose($file);
        };

        return response()->stream($callback, 200, $headers);
    }
}
