<?php

namespace App\Livewire\Enrollments;

use App\Domain\Participant\Models\Participant;
use App\Domain\Shared\Exceptions\DomainException;
use App\Domain\Training\Models\Enrollment;
use App\Domain\Training\Models\TrainingGroup;
use App\Domain\Training\Services\EnrollmentService;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Layout('layouts.app')]
#[Title('نقل مشترك')]
class TransferParticipantWizard extends Component
{
    public int $currentStep = 1;
    public int $totalSteps = 4;
    public bool $completed = false;

    // Step 1: Select Participant & Enrollment
    public string $participantSearch = '';
    public ?int $participantId = null;
    public ?int $enrollmentId = null;

    // Step 2: Destination
    public ?int $destinationGroupId = null;

    // Step 3: Impact & Reason
    public string $reason = '';

    // Cached data for display
    public ?array $selectedParticipant = null;
    public array $activeEnrollments = [];
    public ?array $selectedEnrollment = null;
    public ?array $sourceGroup = null;
    public ?array $destinationGroup = null;

    public function mount(): void
    {
        $this->authorize('enrollments.transfer');
    }

    public function getStepLabels(): array
    {
        return [
            1 => 'اختيار المشترك',
            2 => 'الوجهة',
            3 => 'التأثير',
            4 => 'تأكيد النقل',
        ];
    }

    public function selectParticipant(int $id): void
    {
        $participant = Participant::with('person')->findOrFail($id);
        $this->participantId = $id;
        $this->selectedParticipant = [
            'id' => $participant->id,
            'name' => $participant->person?->name_ar ?? $participant->person?->name ?? '-',
            'participant_number' => $participant->participant_number,
        ];

        $this->loadActiveEnrollments();
    }

    public function updatedParticipantId(): void
    {
        if ($this->participantId) {
            $this->loadActiveEnrollments();
        } else {
            $this->activeEnrollments = [];
        }
        $this->enrollmentId = null;
        $this->selectedEnrollment = null;
        $this->sourceGroup = null;
    }

    private function loadActiveEnrollments(): void
    {
        $enrollments = Enrollment::where('participant_id', $this->participantId)
            ->where('status', 'active')
            ->with(['group', 'program'])
            ->get();

        $this->activeEnrollments = $enrollments->map(fn ($e) => [
            'id' => $e->id,
            'group_name' => $e->group?->name_ar ?? '-',
            'program_name' => $e->program?->name_ar ?? '-',
            'enrollment_date' => $e->enrollment_date?->format('Y-m-d'),
            'group_id' => $e->training_group_id,
            'program_id' => $e->training_program_id,
        ])->toArray();
    }

    public function selectEnrollment(int $id): void
    {
        $enrollment = Enrollment::with(['group', 'program'])->findOrFail($id);
        $this->enrollmentId = $id;
        $this->selectedEnrollment = [
            'id' => $enrollment->id,
            'group_name' => $enrollment->group?->name_ar ?? '-',
            'program_name' => $enrollment->program?->name_ar ?? '-',
            'group_id' => $enrollment->training_group_id,
            'program_id' => $enrollment->training_program_id,
        ];
        $this->sourceGroup = [
            'id' => $enrollment->group?->id,
            'name_ar' => $enrollment->group?->name_ar,
            'current_count' => $enrollment->group?->current_count,
            'max_capacity' => $enrollment->group?->max_capacity,
        ];
    }

    public function selectDestinationGroup(int $id): void
    {
        $group = TrainingGroup::findOrFail($id);
        $this->destinationGroupId = $id;
        $this->destinationGroup = [
            'id' => $group->id,
            'name_ar' => $group->name_ar,
            'current_count' => $group->current_count,
            'max_capacity' => $group->max_capacity,
        ];
    }

    public function nextStep(): void
    {
        $this->validate($this->rulesForStep($this->currentStep));

        if ($this->currentStep < $this->totalSteps) {
            $this->currentStep++;
        }
    }

    public function previousStep(): void
    {
        if ($this->currentStep > 1) {
            $this->currentStep--;
        }
    }

    public function goToStep(int $step): void
    {
        if ($step < $this->currentStep) {
            $this->currentStep = $step;
        }
    }

    public function confirm(): void
    {
        try {
            $enrollment = Enrollment::findOrFail($this->enrollmentId);
            $toGroup = TrainingGroup::findOrFail($this->destinationGroupId);

            app(EnrollmentService::class)->transfer($enrollment, $toGroup, auth()->user());

            $this->completed = true;
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    private function rulesForStep(int $step): array
    {
        return match ($step) {
            1 => [
                'participantId' => 'required|integer|exists:participants,id',
                'enrollmentId' => 'required|integer|exists:enrollments,id',
            ],
            2 => [
                'destinationGroupId' => 'required|integer|exists:training_groups,id',
            ],
            3 => [
                'reason' => 'required|string|min:5|max:500',
            ],
            default => [],
        };
    }

    public function render()
    {
        $searchResults = collect();
        if (strlen($this->participantSearch) >= 2) {
            $searchResults = Participant::with('person')
                ->whereHas('person', function ($q) {
                    $q->where('name_ar', 'ilike', "%{$this->participantSearch}%")
                      ->orWhere('name', 'ilike', "%{$this->participantSearch}%")
                      ->orWhere('phone', 'ilike', "%{$this->participantSearch}%")
                      ->orWhere('national_id', 'ilike', "%{$this->participantSearch}%");
                })
                ->orWhere('participant_number', 'ilike', "%{$this->participantSearch}%")
                ->where('status', 'active')
                ->limit(10)
                ->get();
        }

        $availableGroups = collect();
        if ($this->selectedEnrollment && $this->currentStep >= 2) {
            $availableGroups = TrainingGroup::where('training_program_id', $this->selectedEnrollment['program_id'])
                ->where('id', '!=', $this->selectedEnrollment['group_id'])
                ->whereIn('status', ['forming', 'active'])
                ->orderBy('name_ar')
                ->get();
        }

        return view('livewire.enrollments.transfer-participant-wizard', [
            'searchResults' => $searchResults,
            'availableGroups' => $availableGroups,
        ]);
    }
}
