<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Repositories\StudentTenantRepository;
use App\Repositories\AppointmentRequestRepository;
use App\Repositories\InstructorAvailabilityRepository;
use App\Repositories\InstructorRepository;
use App\Repositories\StudentRepository;
use App\Support\Auth;
use App\Support\Request;
use App\Support\Response;

final class StudentController
{
    private StudentTenantRepository $studentTenantRepo;
    private AppointmentRequestRepository $requestRepo;
    private InstructorAvailabilityRepository $availRepo;
    private InstructorRepository $instructorRepo;
    private StudentRepository $studentRepo;

    public function __construct()
    {
        $this->studentTenantRepo = new StudentTenantRepository();
        $this->requestRepo = new AppointmentRequestRepository();
        $this->availRepo = new InstructorAvailabilityRepository();
        $this->instructorRepo = new InstructorRepository();
        $this->studentRepo = new StudentRepository();
    }

    /**
     * GET /api/v1/student/me
     */
    public function me(Request $request): void
    {
        $user = Auth::requireRole(['student']);

        $tenants = $this->studentTenantRepo->getActiveForUser((int) $user['id']);

        Response::json([
            'user' => [
                'id' => (int) $user['id'],
                'email' => $user['email'],
                'first_name' => $user['first_name'],
                'last_name' => $user['last_name'],
                'role' => $user['role'],
            ],
            'tenants' => $tenants,
        ]);
    }

    /**
     * GET /api/v1/student/instructors?tenant_id=X
     * Liste aller Fahrlehrer einer Fahrschule (mit Kalender-Sichtbarkeit)
     */
    public function instructors(Request $request): void
    {
        $user = Auth::requireRole(['student']);
        $tenantId = (int) ($request->query('tenant_id') ?? $user['tenant_id']);

        // Prüfe ob Student Zugriff auf diesen Tenant hat
        $st = $this->studentTenantRepo->findByUserAndTenant((int) $user['id'], $tenantId);
        if ($st === null || $st['status'] !== 'active') {
            Response::json(['message' => 'Kein Zugriff auf diese Fahrschule'], 403);
        }

        $instructors = $this->instructorRepo->listForTenant($tenantId);

        $result = [];
        foreach ($instructors as $i) {
            if ($i['is_active'] !== 1 || $i['booking_enabled'] !== 1) {
                continue;
            }
            $result[] = [
                'id' => $i['id'],
                'first_name' => $i['first_name'],
                'last_name' => $i['last_name'],
                'color' => $i['color'] ?? '#3b82f6',
            ];
        }

        Response::json(['data' => $result]);
    }

    /**
     * GET /api/v1/student/instructors/{id}/slots?from=&to=&tenant_id=X
     * Belegte Slots für einen Fahrlehrer (was der Fahrschüler sehen darf)
     */
    public function instructorSlots(Request $request, array $params): void
    {
        $user = Auth::requireRole(['student']);
        $instructorId = (int) $params['id'];
        $from = (string) ($request->query('from') ?? date('Y-m-d'));
        $to = (string) ($request->query('to') ?? date('Y-m-d', strtotime('+30 days')));
        $tenantId = (int) ($request->query('tenant_id') ?? $user['tenant_id']);

        // Zugriff prüfen
        $st = $this->studentTenantRepo->findByUserAndTenant((int) $user['id'], $tenantId);
        if ($st === null || $st['status'] !== 'active') {
            Response::json(['message' => 'Kein Zugriff'], 403);
        }

        // Instructor existiert?
        $instructor = $this->instructorRepo->findById($instructorId);
        if ($instructor === null) {
            Response::json(['message' => 'Fahrlehrer nicht gefunden'], 404);
        }

        // Availability holen
        $availability = $this->availRepo->getActiveForInstructor($instructorId);

        Response::json([
            'instructor' => [
                'id' => $instructor['id'],
                'first_name' => $instructor['first_name'],
                'last_name' => $instructor['last_name'],
            ],
            'availability' => $availability,
            'from' => $from,
            'to' => $to,
        ]);
    }

    /**
     * POST /api/v1/student/appointment-requests
     * Neue Terminanfrage eines Fahrschülers
     */
    public function createAppointmentRequest(Request $request): void
    {
        $user = Auth::requireRole(['student']);
        $payload = $request->input();

        $instructorId = (int) ($payload['instructor_id'] ?? 0);
        $lessonTypeId = (int) ($payload['lesson_type_id'] ?? 0);
        $start = trim((string) ($payload['start'] ?? ''));
        $end = trim((string) ($payload['end'] ?? ''));
        $notes = trim((string) ($payload['notes'] ?? ''));
        $tenantId = (int) ($payload['tenant_id'] ?? $user['tenant_id']);

        if ($instructorId <= 0 || $lessonTypeId <= 0 || $start === '' || $end === '') {
            Response::json(['message' => 'instructor_id, lesson_type_id, start und end sind erforderlich'], 422);
        }

        // Tenant-Zugriff prüfen
        $st = $this->studentTenantRepo->findByUserAndTenant((int) $user['id'], $tenantId);
        if ($st === null || $st['status'] !== 'active') {
            Response::json(['message' => 'Kein Zugriff auf diese Fahrschule'], 403);
        }

        // Instructor prüfen
        $instructor = $this->instructorRepo->findById($instructorId);
        if ($instructor === null) {
            Response::json(['message' => 'Fahrlehrer nicht gefunden'], 404);
        }

        if ($instructor['booking_enabled'] !== 1) {
            Response::json(['message' => 'Dieser Fahrlehrer akzeptiert keine Anfragen'], 400);
        }

        // Anfrage erstellen
        $record = $this->requestRepo->create(
            (int) $user['id'],
            $instructorId,
            $lessonTypeId,
            $start,
            $end,
            $notes
        );

        Response::json(['data' => $record], 201);
    }

    /**
     * GET /api/v1/student/appointment-requests
     */
    public function appointmentRequests(Request $request): void
    {
        $user = Auth::requireRole(['student']);
        $requests = $this->requestRepo->getForStudent((int) $user['id']);

        Response::json(['data' => $requests]);
    }

    /**
     * POST /api/v1/student/add-tenant
     * Fahrschüler gibt neuen Code ein → neuer pending tenant
     */
    public function addTenant(Request $request): void
    {
        $user = Auth::requireRole(['student']);
        $payload = $request->input();
        $code = trim((string) ($payload['code'] ?? ''));

        if ($code === '') {
            Response::json(['message' => 'code ist erforderlich'], 422);
        }

        // Code → Tenant finden
        $tenantRepo = new \App\Repositories\TenantRegistrationCodeRepository();
        $tenantCode = $tenantRepo->findByCode($code);
        if ($tenantCode === null) {
            Response::json(['message' => 'Ungültiger Code'], 400);
        }

        $tenantId = (int) $tenantCode['tenant_id'];

        // Already connected?
        $existing = $this->studentTenantRepo->findByUserAndTenant((int) $user['id'], $tenantId);
        if ($existing !== null) {
            Response::json(['message' => 'Du bist bereits mit dieser Fahrschule verbunden'], 400);
        }

        $record = $this->studentTenantRepo->create((int) $user['id'], $tenantId, 'pending');

        Response::json([
            'data' => $record,
            'message' => 'Anfrage gesendet, warte auf Bestätigung durch die Fahrschule',
        ], 201);
    }
}