<?php

namespace App\Livewire\Enrollments;

use App\Domain\Financial\Services\InvoiceService;
use App\Domain\Participant\Models\Participant;
use App\Domain\Pricing\Services\PricingService;
use App\Domain\Shared\Exceptions\DomainException;
use App\Domain\Training\Models\Enrollment;
use App\Domain\Training\Models\TrainingGroup;
use App\Domain\Training\Models\TrainingProgram;
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;

    // Mode: 'single' or 'bulk'
    public string $mode = 'bulk';

    // Step 1: Source selection
    public ?int $sourceGroupId = null;
    public ?array $sourceGroupInfo = null;
    public string $participantSearch = '';

    // Selected participants (enrollment_id => participant info)
    public array $selectedParticipants = [];
    public bool $selectAll = false;

    // Single mode
    public ?int $singleParticipantId = null;
    public ?int $singleEnrollmentId = null;
    public ?array $singleParticipantInfo = null;
    public array $singleEnrollments = [];

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

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

    // Step 4: Results
    public array $transferResults = [];
    public int $successCount = 0;
    public int $failCount = 0;

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

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

    // --- Mode ---

    public function setMode(string $mode): void
    {
        $this->mode = $mode;
        $this->reset(['sourceGroupId', 'sourceGroupInfo', 'participantSearch', 'selectedParticipants', 'selectAll', 'singleParticipantId', 'singleEnrollmentId', 'singleParticipantInfo', 'singleEnrollments']);
    }

    // --- Bulk Mode: Source Group ---

    public function selectSourceGroup(int $id): void
    {
        $group = TrainingGroup::with('program')->findOrFail($id);
        $this->sourceGroupId = $id;
        $this->sourceGroupInfo = [
            'id' => $group->id,
            'name_ar' => $group->name_ar,
            'program_name' => $group->program?->name_ar ?? '-',
            'current_count' => $group->current_count,
            'max_capacity' => $group->max_capacity,
            'program_id' => $group->training_program_id,
        ];
        $this->selectedParticipants = [];
        $this->selectAll = false;
    }

    public function toggleParticipant(int $enrollmentId): void
    {
        if (isset($this->selectedParticipants[$enrollmentId])) {
            unset($this->selectedParticipants[$enrollmentId]);
            $this->selectAll = false;
        } else {
            $enrollment = Enrollment::with('participant.person')->find($enrollmentId);
            if ($enrollment) {
                $this->selectedParticipants[$enrollmentId] = [
                    'enrollment_id' => $enrollmentId,
                    'participant_id' => $enrollment->participant_id,
                    'name' => $enrollment->participant?->person?->name_ar ?? $enrollment->participant?->person?->name ?? '-',
                    'participant_number' => $enrollment->participant?->participant_number,
                ];
            }
        }
    }

    public function toggleSelectAll(): void
    {
        if ($this->selectAll) {
            $this->selectedParticipants = [];
            $this->selectAll = false;
            return;
        }

        $enrollments = Enrollment::where('training_group_id', $this->sourceGroupId)
            ->where('status', 'active')
            ->with('participant.person')
            ->get();

        $this->selectedParticipants = [];
        foreach ($enrollments as $enrollment) {
            $this->selectedParticipants[$enrollment->id] = [
                'enrollment_id' => $enrollment->id,
                'participant_id' => $enrollment->participant_id,
                'name' => $enrollment->participant?->person?->name_ar ?? $enrollment->participant?->person?->name ?? '-',
                'participant_number' => $enrollment->participant?->participant_number,
            ];
        }
        $this->selectAll = true;
    }

    // --- Single Mode ---

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

        $this->singleEnrollments = Enrollment::where('participant_id', $id)
            ->where('status', 'active')
            ->with(['group', 'program'])
            ->get()
            ->map(fn ($e) => [
                'id' => $e->id,
                'group_name' => $e->group?->name_ar ?? '-',
                'program_name' => $e->program?->name_ar ?? '-',
                'group_id' => $e->training_group_id,
                'program_id' => $e->training_program_id,
            ])->toArray();
    }

    public function selectSingleEnrollment(int $enrollmentId): void
    {
        $enrollment = Enrollment::with(['participant.person', 'group'])->findOrFail($enrollmentId);
        $this->singleEnrollmentId = $enrollmentId;
        $this->sourceGroupId = $enrollment->training_group_id;
        $this->sourceGroupInfo = [
            'id' => $enrollment->group?->id,
            'name_ar' => $enrollment->group?->name_ar,
            'program_name' => $enrollment->program?->name_ar ?? '-',
            'current_count' => $enrollment->group?->current_count,
            'max_capacity' => $enrollment->group?->max_capacity,
            'program_id' => $enrollment->training_program_id,
        ];

        $this->selectedParticipants = [
            $enrollmentId => [
                'enrollment_id' => $enrollmentId,
                'participant_id' => $enrollment->participant_id,
                'name' => $enrollment->participant?->person?->name_ar ?? $enrollment->participant?->person?->name ?? '-',
                'participant_number' => $enrollment->participant?->participant_number,
            ],
        ];
    }

    public function clearSingleParticipant(): void
    {
        $this->reset(['singleParticipantId', 'singleParticipantInfo', 'singleEnrollments', 'singleEnrollmentId', 'selectedParticipants', 'sourceGroupId', 'sourceGroupInfo']);
    }

    // --- Destination ---

    public function selectDestinationProgram(?int $id): void
    {
        $this->destinationProgramId = $id;
        $this->destinationGroupId = null;
        $this->destinationGroupInfo = null;
    }

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

    // --- Navigation ---

    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;
        }
    }

    // --- Confirm ---

    public function confirm(): void
    {
        $enrollmentService = app(EnrollmentService::class);
        $toGroup = TrainingGroup::findOrFail($this->destinationGroupId);
        $actor = auth()->user();

        $this->transferResults = [];
        $this->successCount = 0;
        $this->failCount = 0;

        foreach ($this->selectedParticipants as $enrollmentId => $info) {
            try {
                $enrollment = Enrollment::findOrFail($enrollmentId);
                $enrollmentService->transfer($enrollment, $toGroup, $actor);
                $this->transferResults[] = [
                    'name' => $info['name'],
                    'status' => 'success',
                    'message' => __('تم النقل بنجاح'),
                ];
                $this->successCount++;
            } catch (DomainException $e) {
                $this->transferResults[] = [
                    'name' => $info['name'],
                    'status' => 'error',
                    'message' => $e->getMessage(),
                ];
                $this->failCount++;
            } catch (\Throwable $e) {
                $this->transferResults[] = [
                    'name' => $info['name'],
                    'status' => 'error',
                    'message' => __('خطأ غير متوقع'),
                ];
                $this->failCount++;
            }
        }

        $this->completed = true;
    }

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

    public function messages(): array
    {
        return [
            'selectedParticipants.required' => 'يجب اختيار مشترك واحد على الأقل',
            'selectedParticipants.min' => 'يجب اختيار مشترك واحد على الأقل',
            'destinationGroupId.required' => 'يجب اختيار المجموعة الوجهة',
            'reason.required' => 'يجب كتابة سبب النقل',
            'reason.min' => 'سبب النقل قصير جدًا',
        ];
    }

    public function render()
    {
        // Search results for single mode
        $searchResults = collect();
        if ($this->mode === 'single' && strlen($this->participantSearch) >= 2 && !$this->singleParticipantInfo) {
            $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('participant_number', 'ilike', "%{$this->participantSearch}%")
                ->limit(10)
                ->get();
        }

        // Source groups for bulk mode
        $sourceGroups = collect();
        if ($this->mode === 'bulk' && !$this->sourceGroupId) {
            $sourceGroups = TrainingGroup::whereIn('status', ['active', 'forming'])
                ->where('current_count', '>', 0)
                ->with('program')
                ->orderBy('name_ar')
                ->get();
        }

        // Source group enrollments (for bulk selection)
        $sourceEnrollments = collect();
        if ($this->mode === 'bulk' && $this->sourceGroupId) {
            $query = Enrollment::where('training_group_id', $this->sourceGroupId)
                ->where('status', 'active')
                ->with('participant.person');

            if (strlen($this->participantSearch) >= 2) {
                $search = $this->participantSearch;
                $query->whereHas('participant.person', function ($q) use ($search) {
                    $q->where('name_ar', 'ilike', "%{$search}%")
                      ->orWhere('name', 'ilike', "%{$search}%")
                      ->orWhere('phone', 'ilike', "%{$search}%");
                });
            }

            $sourceEnrollments = $query->get();
        }

        // Destination options
        $availablePrograms = collect();
        $availableGroups = collect();
        if ($this->currentStep >= 2 && $this->sourceGroupId) {
            $availablePrograms = TrainingProgram::where('status', 'active')
                ->orderBy('name_ar')
                ->get();

            $targetProgramId = $this->destinationProgramId ?? ($this->sourceGroupInfo['program_id'] ?? null);

            if ($targetProgramId) {
                $availableGroups = TrainingGroup::where('training_program_id', $targetProgramId)
                    ->where('id', '!=', $this->sourceGroupId)
                    ->whereIn('status', ['forming', 'active'])
                    ->with('program')
                    ->orderBy('name_ar')
                    ->get();
            }
        }

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