<?php

namespace App\Http\Controllers\Api\V1;

use App\Domain\Attendance\Models\AttendanceRecord;
use App\Domain\Financial\Models\Invoice;
use App\Domain\Participant\Models\Participant;
use App\Domain\Training\Models\Enrollment;
use App\Domain\Training\Models\TrainingSession;
use App\Http\Controllers\Controller;
use App\Http\Resources\Api\V1\AttendanceResource;
use App\Http\Resources\Api\V1\EnrollmentResource;
use App\Http\Resources\Api\V1\InvoiceResource;
use App\Http\Resources\Api\V1\ParticipantResource;
use App\Http\Resources\Api\V1\SessionResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class ParticipantController extends Controller
{
    public function children(Request $request): JsonResponse
    {
        $user = $request->user();
        $participants = $this->getAuthorizedParticipants($user);

        return response()->json([
            'data' => ParticipantResource::collection($participants),
        ]);
    }

    public function show(string $uuid, Request $request): JsonResponse
    {
        $participant = $this->findAuthorized($uuid, $request->user());

        $participant->load(['person', 'primaryActivity', 'branch', 'activeEnrollments.group.program']);

        return response()->json([
            'data' => new ParticipantResource($participant),
        ]);
    }

    public function summary(string $uuid, Request $request): JsonResponse
    {
        $participant = $this->findAuthorized($uuid, $request->user());

        $activeEnrollments = $participant->activeEnrollments()->count();

        $attendanceRate = $this->calculateAttendanceRate($participant);

        $outstandingBalance = Invoice::where('billable_type', 'App\\Domain\\Participant\\Models\\Participant')
            ->where('billable_id', $participant->id)
            ->whereNotIn('status', ['cancelled', 'draft', 'paid'])
            ->sum('balance_due');

        $nextSession = $this->getNextSession($participant);

        return response()->json([
            'data' => [
                'participant_uuid' => $participant->uuid,
                'name_ar' => $participant->person->name_ar,
                'photo_url' => $participant->photo_path ? asset('storage/' . $participant->photo_path) : null,
                'status' => $participant->status->value,
                'active_enrollments' => $activeEnrollments,
                'attendance_rate' => $attendanceRate,
                'outstanding_balance' => $outstandingBalance,
                'next_session' => $nextSession ? new SessionResource($nextSession) : null,
            ],
        ]);
    }

    public function schedule(string $uuid, Request $request): JsonResponse
    {
        $participant = $this->findAuthorized($uuid, $request->user());

        $groupIds = $participant->activeEnrollments()->pluck('training_group_id');

        $sessions = TrainingSession::whereIn('training_group_id', $groupIds)
            ->where('session_date', '>=', now()->toDateString())
            ->where('session_date', '<=', now()->addDays(7)->toDateString())
            ->whereIn('status', ['scheduled', 'in_progress'])
            ->with(['group.program.activity', 'facility'])
            ->orderBy('session_date')
            ->orderBy('start_time')
            ->get();

        return response()->json([
            'data' => SessionResource::collection($sessions),
        ]);
    }

    public function attendance(string $uuid, Request $request): JsonResponse
    {
        $participant = $this->findAuthorized($uuid, $request->user());

        $records = AttendanceRecord::where('subject_type', 'App\\Domain\\Participant\\Models\\Participant')
            ->where('subject_id', $participant->id)
            ->with(['session.group.program'])
            ->orderByDesc('date')
            ->paginate(20);

        $rate = $this->calculateAttendanceRate($participant);

        return response()->json([
            'rate' => $rate,
            'data' => AttendanceResource::collection($records),
            'meta' => [
                'current_page' => $records->currentPage(),
                'last_page' => $records->lastPage(),
                'per_page' => $records->perPage(),
                'total' => $records->total(),
            ],
        ]);
    }

    public function invoices(string $uuid, Request $request): JsonResponse
    {
        $participant = $this->findAuthorized($uuid, $request->user());

        $invoices = Invoice::where('billable_type', 'App\\Domain\\Participant\\Models\\Participant')
            ->where('billable_id', $participant->id)
            ->whereNotIn('status', ['cancelled', 'draft'])
            ->with('items')
            ->orderByDesc('created_at')
            ->paginate(15);

        return response()->json([
            'data' => InvoiceResource::collection($invoices),
            'meta' => [
                'current_page' => $invoices->currentPage(),
                'last_page' => $invoices->lastPage(),
                'per_page' => $invoices->perPage(),
                'total' => $invoices->total(),
            ],
        ]);
    }

    public function enrollments(string $uuid, Request $request): JsonResponse
    {
        $participant = $this->findAuthorized($uuid, $request->user());

        $enrollments = Enrollment::where('participant_id', $participant->id)
            ->whereIn('status', ['active', 'pending'])
            ->with(['group.program.activity', 'group.schedules'])
            ->get();

        return response()->json([
            'data' => EnrollmentResource::collection($enrollments),
        ]);
    }

    private function findAuthorized(string $uuid, $user): Participant
    {
        $participant = Participant::where('uuid', $uuid)->firstOrFail();
        $authorized = $this->getAuthorizedParticipants($user);

        if (!$authorized->contains('id', $participant->id)) {
            abort(403, 'غير مصرح لك بالوصول لهذا المشترك');
        }

        return $participant;
    }

    private function getAuthorizedParticipants($user): \Illuminate\Support\Collection
    {
        $personId = $user->person_id;
        if (!$personId) {
            return collect();
        }

        $direct = Participant::where('person_id', $personId)
            ->with(['person', 'activeEnrollments.group.program.activity'])
            ->get();

        $guardian = \App\Domain\Identity\Models\Guardian::where('person_id', $personId)->first();
        $guardianParticipants = collect();

        if ($guardian) {
            $guardianParticipants = $guardian->participants()
                ->with(['person', 'activeEnrollments.group.program.activity'])
                ->get();
        }

        return $direct->merge($guardianParticipants)->unique('id');
    }

    private function calculateAttendanceRate(Participant $participant): float
    {
        $total = AttendanceRecord::where('subject_type', 'App\\Domain\\Participant\\Models\\Participant')
            ->where('subject_id', $participant->id)
            ->whereNotIn('status', ['cancelled', 'exempt'])
            ->count();

        if ($total === 0) {
            return 0;
        }

        $positive = AttendanceRecord::where('subject_type', 'App\\Domain\\Participant\\Models\\Participant')
            ->where('subject_id', $participant->id)
            ->whereIn('status', ['present', 'late', 'partial'])
            ->count();

        return round($positive / $total * 100, 1);
    }

    private function getNextSession(Participant $participant): ?TrainingSession
    {
        $groupIds = $participant->activeEnrollments()->pluck('training_group_id');

        return TrainingSession::whereIn('training_group_id', $groupIds)
            ->where('session_date', '>=', now()->toDateString())
            ->whereIn('status', ['scheduled'])
            ->orderBy('session_date')
            ->orderBy('start_time')
            ->first();
    }
}
