<?php

namespace App\Http\Controllers\Mentorship;

use App\Http\Controllers\Controller;
use App\Models\Mentorship\Session;
use App\Models\Mentorship\Assignment;
use App\Services\Mentorship\SessionService;
use App\Http\Requests\Mentorship\SessionRequest;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;

class SessionController extends Controller
{
    protected SessionService $sessionService;

    public function __construct(SessionService $sessionService)
    {
        $this->sessionService = $sessionService;
    }

    /**
     * Display a listing of sessions.
     */
    public function index(Request $request)
    {
        abort_unless(auth()->user()->can('view mentorship sessions'), 403);

        $user = auth()->user();

        $filters = [
            'status' => $request->get('status'),
            'type' => $request->get('type'),
            'programme_id' => $request->get('programme_id'),
            'assignment_id' => $request->get('assignment_id'),
            'user_id' => $request->get('user_id'),
            'start_date' => $request->get('start_date'),
            'end_date' => $request->get('end_date'),
            'upcoming' => $request->get('upcoming'),
            'past' => $request->get('past'),
            'sort_by' => $request->get('sort_by', 'start_time'),
            'sort_order' => $request->get('sort_order', 'asc'),
        ];

        // Mentors and Mentees only see sessions for their own assignments
        $isOwnOnly = $user->hasRole('Mentor') || $user->hasRole('Mentee');
        if ($isOwnOnly) {
            $filters['user_id'] = $user->id;
        }

        $sessions = $this->sessionService->getSessions($filters);

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

    /**
     * Show the form for creating a new session.
     */
    public function create(Request $request)
    {
        abort_unless(auth()->user()->can('create mentorship sessions'), 403);

        $assignmentId = $request->get('assignment_id');
        $assignment = $assignmentId ? Assignment::with(['programme', 'mentor', 'mentee'])->find($assignmentId) : null;

        return view('mentorship.sessions.create', compact('assignment'));
    }

    /**
     * Store a newly created session.
     */
    public function store(SessionRequest $request)
    {
        abort_unless(auth()->user()->can('create mentorship sessions'), 403);

        try {
            $session = $this->sessionService->create($request->validated());

            return redirect()
                ->route('mentorship.sessions.show', $session)
                ->with('success', 'Session created successfully.');
        } catch (\Exception $e) {
            return back()
                ->withInput()
                ->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * Display the specified session.
     */
    public function show(Session $session)
    {
        abort_unless(auth()->user()->can('view mentorship sessions'), 403);

        $user = auth()->user();

        // Mentors and Mentees can only view sessions for their own assignments
        if ($user->hasRole('Mentor') || $user->hasRole('Mentee')) {
            $session->loadMissing('assignment');
            abort_unless(
                $session->assignment->mentor_id === $user->id ||
                $session->assignment->mentee_id === $user->id,
                403
            );
        }

        $session->load([
            'assignment.programme',
            'assignment.mentor',
            'assignment.mentee',
            'programme',
            'creator',
        ]);

        return view('mentorship.sessions.show', compact('session'));
    }

    /**
     * Show the form for editing the specified session.
     */
    public function edit(Session $session)
    {
        abort_unless(auth()->user()->can('edit mentorship sessions'), 403);

        $session->load(['assignment.programme', 'assignment.mentor', 'assignment.mentee']);

        return view('mentorship.sessions.edit', compact('session'));
    }

    /**
     * Update the specified session.
     */
    public function update(SessionRequest $request, Session $session)
    {
        abort_unless(auth()->user()->can('edit mentorship sessions'), 403);

        try {
            $this->sessionService->update($session, $request->validated());

            return redirect()
                ->route('mentorship.sessions.show', $session)
                ->with('success', 'Session updated successfully.');
        } catch (\Exception $e) {
            return back()
                ->withInput()
                ->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * Remove the specified session.
     */
    public function destroy(Session $session)
    {
        abort_unless(auth()->user()->can('delete mentorship sessions'), 403);

        try {
            $session->delete();

            return redirect()
                ->route('mentorship.sessions.index')
                ->with('success', 'Session deleted successfully.');
        } catch (\Exception $e) {
            return back()->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * Cancel a session.
     */
    public function cancel(Request $request, Session $session)
    {
        abort_unless(auth()->user()->can('cancel mentorship sessions'), 403);

        $request->validate([
            'reason' => 'required|string|max:1000',
        ]);

        try {
            $this->sessionService->cancel($session, $request->reason);

            return redirect()
                ->route('mentorship.sessions.show', $session)
                ->with('success', 'Session cancelled.');
        } catch (\Exception $e) {
            return back()->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * Complete a session.
     */
    public function complete(Request $request, Session $session)
    {
        abort_unless(auth()->user()->can('complete mentorship sessions'), 403);

        $request->validate([
            'summary' => 'nullable|string|max:5000',
            'action_items' => 'nullable|string|max:2000',
            'mentor_attended' => 'boolean',
            'mentee_attended' => 'boolean',
            'mentor_rating' => 'nullable|integer|min:1|max:5',
            'mentor_feedback' => 'nullable|string|max:2000',
            'mentee_rating' => 'nullable|integer|min:1|max:5',
            'mentee_feedback' => 'nullable|string|max:2000',
        ]);

        try {
            $this->sessionService->complete($session, $request->validated());

            return redirect()
                ->route('mentorship.sessions.show', $session)
                ->with('success', 'Session marked as completed.');
        } catch (\Exception $e) {
            return back()->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * Reschedule a session.
     */
    public function reschedule(Request $request, Session $session)
    {
        abort_unless(auth()->user()->can('edit mentorship sessions'), 403);

        $request->validate([
            'title' => 'required|string|max:191',
            'start_time' => 'required|date|after:now',
            'end_time' => 'required|date|after:start_time',
            'type' => 'required|in:online,in_person',
            'venue' => 'required_if:type,in_person|nullable|string|max:500',
            'reschedule_reason' => 'nullable|string|max:500',
        ]);

        try {
            $newSession = $this->sessionService->reschedule($session, $request->validated());

            return redirect()
                ->route('mentorship.sessions.show', $newSession)
                ->with('success', 'Session rescheduled successfully.');
        } catch (\Exception $e) {
            return back()->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * Get calendar events.
     */
    public function calendar(Request $request): JsonResponse
    {
        $startDate = $request->get('start');
        $endDate = $request->get('end');
        $userId = auth()->id();

        $events = $this->sessionService->getCalendarEvents($userId, $startDate, $endDate);

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

    /**
     * Display calendar view.
     */
    public function calendarView()
    {
        abort_unless(auth()->user()->can('view mentorship sessions'), 403);

        return view('mentorship.sessions.calendar');
    }

    /**
     * Record attendance.
     */
    public function recordAttendance(Request $request, Session $session): JsonResponse
    {
        abort_unless(auth()->user()->can('edit mentorship sessions'), 403);

        $request->validate([
            'role' => 'required|in:mentor,mentee',
            'attended' => 'required|boolean',
        ]);

        $session->recordAttendance($request->role, $request->attended);

        return response()->json([
            'success' => true,
            'message' => 'Attendance recorded.',
        ]);
    }

    /**
     * Get sessions for an assignment (AJAX).
     */
    public function getForAssignment(Assignment $assignment): JsonResponse
    {
        $sessions = $assignment->sessions()
            ->orderBy('start_time', 'desc')
            ->get();

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