<?php

namespace App\Livewire\Groups;

use App\Domain\Attendance\Enums\AttendanceStatus;
use App\Domain\Attendance\Models\AttendanceRecord;
use App\Domain\Financial\Enums\InvoiceStatus;
use App\Domain\Financial\Models\Invoice;
use App\Domain\Participant\Models\Participant;
use App\Domain\Scheduling\Models\Assignment;
use App\Domain\Training\Enums\SessionStatus;
use App\Domain\Training\Models\Enrollment;
use App\Domain\Training\Models\TrainingGroup;
use App\Domain\Training\Models\TrainingSession;
use App\Models\User;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Layout('layouts.app')]
#[Title('تفاصيل المجموعة')]
class GroupShow extends Component
{
    public TrainingGroup $group;
    public string $activeTab = 'overview';
    public ?int $assignTrainerId = null;

    public function mount(TrainingGroup $group): void
    {
        $this->authorize('groups.list');

        $this->group = $group->load([
            'program',
            'branch',
            'headTrainer',
            'creator',
            'schedules',
            'schedules.facility',
            'schedules.trainer',
        ]);
    }

    public function assignTrainer(): void
    {
        $this->authorize('groups.update');

        if (!$this->assignTrainerId) {
            return;
        }

        $exists = Assignment::where('assignable_type', TrainingGroup::class)
            ->where('assignable_id', $this->group->id)
            ->where('user_id', $this->assignTrainerId)
            ->where('status', 'active')
            ->exists();

        if ($exists) {
            session()->flash('error', __('هذا المدرب مُعيَّن بالفعل لهذه المجموعة'));
            return;
        }

        Assignment::create([
            'academy_id' => $this->group->academy_id,
            'user_id' => $this->assignTrainerId,
            'assignable_type' => TrainingGroup::class,
            'assignable_id' => $this->group->id,
            'role_label' => 'مدرب',
            'scope' => 'full',
            'status' => 'active',
            'is_primary' => false,
            'start_date' => now()->toDateString(),
            'created_by' => auth()->id(),
        ]);

        $this->assignTrainerId = null;
        session()->flash('success', __('تم تعيين المدرب بنجاح'));
    }

    public function removeTrainer(int $assignmentId): void
    {
        $this->authorize('groups.update');

        Assignment::where('id', $assignmentId)
            ->where('assignable_type', TrainingGroup::class)
            ->where('assignable_id', $this->group->id)
            ->update(['status' => 'cancelled']);

        session()->flash('success', __('تم إلغاء تعيين المدرب'));
    }

    public function render()
    {
        // Active enrollments with participant details
        $activeEnrollments = Enrollment::where('training_group_id', $this->group->id)
            ->where('status', 'active')
            ->with(['participant.person'])
            ->orderBy('enrollment_date')
            ->get();

        // Payment status per participant: has unpaid/overdue invoices this month?
        $participantIds = $activeEnrollments->pluck('participant_id')->toArray();
        $unpaidParticipantIds = [];
        if ($participantIds) {
            $unpaidParticipantIds = Invoice::where('billable_type', Participant::class)
                ->whereIn('billable_id', $participantIds)
                ->whereIn('status', [InvoiceStatus::Sent, InvoiceStatus::Overdue, InvoiceStatus::PartiallyPaid])
                ->where('due_amount', '>', 0)
                ->whereNull('deleted_at')
                ->pluck('billable_id')
                ->unique()
                ->toArray();
        }

        // Also flag enrollments where next_billing_date is past and payment_status != paid
        $overdueEnrollmentParticipantIds = $activeEnrollments
            ->filter(fn ($e) => $e->next_billing_date && $e->next_billing_date->isPast() && ($e->payment_status?->value ?? $e->payment_status) !== 'paid')
            ->pluck('participant_id')
            ->toArray();

        $notPaidParticipantIds = array_unique(array_merge($unpaidParticipantIds, $overdueEnrollmentParticipantIds));

        // All enrollments count (any status)
        $totalEnrollments = Enrollment::where('training_group_id', $this->group->id)
            ->whereNotIn('status', ['cancelled'])
            ->count();

        // Sessions: recent completed + upcoming scheduled
        $recentSessions = TrainingSession::where('training_group_id', $this->group->id)
            ->where('session_date', '<', now()->toDateString())
            ->orderByDesc('session_date')
            ->limit(20)
            ->get();

        $upcomingSessions = TrainingSession::where('training_group_id', $this->group->id)
            ->where('session_date', '>=', now()->toDateString())
            ->orderBy('session_date')
            ->limit(10)
            ->get();

        // Session stats
        $totalSessions = TrainingSession::where('training_group_id', $this->group->id)->count();
        $completedSessions = TrainingSession::where('training_group_id', $this->group->id)
            ->where('status', SessionStatus::Completed)
            ->count();

        // Attendance stats for the group (across all sessions)
        $sessionIds = TrainingSession::where('training_group_id', $this->group->id)
            ->pluck('id');

        $attendanceQuery = AttendanceRecord::whereIn('training_session_id', $sessionIds);

        $totalAttendanceRecords = (clone $attendanceQuery)->count();
        $presentCount = (clone $attendanceQuery)->where('status', AttendanceStatus::Present)->count();
        $lateCount = (clone $attendanceQuery)->where('status', AttendanceStatus::Late)->count();
        $absentCount = (clone $attendanceQuery)->whereIn('status', [AttendanceStatus::Absent, AttendanceStatus::NoShow])->count();
        $partialCount = (clone $attendanceQuery)->where('status', AttendanceStatus::Partial)->count();
        $excusedCount = (clone $attendanceQuery)->where('status', AttendanceStatus::Excused)->count();
        $cancelledExempt = (clone $attendanceQuery)->whereIn('status', [AttendanceStatus::Cancelled, AttendanceStatus::Exempt])->count();

        $attendanceDenominator = $totalAttendanceRecords - $cancelledExempt;
        $attendanceRate = $attendanceDenominator > 0
            ? round(($presentCount + $lateCount + $partialCount) / $attendanceDenominator * 100, 1)
            : 0;

        // Capacity percentage
        $capacityPercent = $this->group->max_capacity > 0
            ? round(($this->group->current_count / $this->group->max_capacity) * 100, 1)
            : 0;

        // Per-participant attendance rates for enrollments tab
        $participantAttendanceRates = [];
        if ($activeEnrollments->isNotEmpty() && $sessionIds->isNotEmpty()) {
            $participantClass = \App\Domain\Participant\Models\Participant::class;
            foreach ($activeEnrollments as $enrollment) {
                $pQuery = AttendanceRecord::whereIn('training_session_id', $sessionIds)
                    ->where('subject_type', $participantClass)
                    ->where('subject_id', $enrollment->participant_id);

                $pTotal = (clone $pQuery)->count();
                $pExcluded = (clone $pQuery)->whereIn('status', [AttendanceStatus::Cancelled, AttendanceStatus::Exempt])->count();
                $pPositive = (clone $pQuery)->whereIn('status', [AttendanceStatus::Present, AttendanceStatus::Late, AttendanceStatus::Partial])->count();

                $pDenom = $pTotal - $pExcluded;
                $participantAttendanceRates[$enrollment->participant_id] = $pDenom > 0
                    ? round(($pPositive / $pDenom) * 100, 1)
                    : null;
            }
        }

        // Waitlist count
        $waitlistCount = $this->group->waitlist_count ?? 0;

        // Trainer assignments for this group
        $trainerAssignments = Assignment::where('assignable_type', TrainingGroup::class)
            ->where('assignable_id', $this->group->id)
            ->where('status', 'active')
            ->with('user')
            ->get();

        $availableTrainers = User::whereHas('roles', fn ($q) => $q->whereIn('slug', ['trainer', 'head_trainer']))
            ->where('status', 'active')
            ->whereNotIn('id', $trainerAssignments->pluck('user_id')->toArray())
            ->orderBy('name_ar')
            ->get(['id', 'name_ar', 'name']);

        return view('livewire.groups.group-show', [
            'activeEnrollments' => $activeEnrollments,
            'notPaidParticipantIds' => $notPaidParticipantIds,
            'totalEnrollments' => $totalEnrollments,
            'recentSessions' => $recentSessions,
            'upcomingSessions' => $upcomingSessions,
            'totalSessions' => $totalSessions,
            'completedSessions' => $completedSessions,
            'totalAttendanceRecords' => $totalAttendanceRecords,
            'presentCount' => $presentCount,
            'lateCount' => $lateCount,
            'absentCount' => $absentCount,
            'partialCount' => $partialCount,
            'excusedCount' => $excusedCount,
            'attendanceRate' => $attendanceRate,
            'capacityPercent' => $capacityPercent,
            'participantAttendanceRates' => $participantAttendanceRates,
            'waitlistCount' => $waitlistCount,
            'trainerAssignments' => $trainerAssignments,
            'availableTrainers' => $availableTrainers,
        ]);
    }
}
