<?php

namespace App\Livewire\Receptionist;

use App\Domain\Participant\Models\Participant;
use App\Domain\Pricing\Models\BasePrice;
use App\Domain\Shared\DTOs\ProrationResult;
use App\Domain\Shared\Exceptions\DomainException;
use App\Domain\Shared\Services\ProrationService;
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Domain\Training\Models\Activity;
use App\Domain\Training\Models\Enrollment;
use App\Domain\Training\Models\TrainingProgram;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Layout('layouts.app')]
#[Title('تسجيل في برنامج')]
class EnrollExistingWizard extends Component
{
    use UsesBranchScope;

    public ?int $branchId = null;

    public int $currentStep = 1;
    public int $totalSteps = 4;

    // Step 1: Search
    public string $search = '';
    public ?int $selected_participant_id = null;
    public ?string $selected_participant_name = null;

    // Step 2: Program selection
    public ?int $selected_activity_id = null;
    public ?int $selected_program_id = null;

    // Step 3: Payment
    public bool $pay_now = false;
    public string $payment_method = 'cash';

    // Result
    public bool $completed = false;
    public ?string $created_participant_uuid = null;
    public ?string $created_invoice_uuid = null;

    public function mount(): void
    {
        $this->authorize('enrollments.create');
        $this->branchId = $this->getActiveBranchIdOrFail();
    }

    public function rules(): array
    {
        return match ($this->currentStep) {
            1 => [
                'selected_participant_id' => 'required|exists:participants,id',
            ],
            2 => [
                'selected_activity_id' => 'required|exists:activities,id',
                'selected_program_id' => 'required|exists:training_programs,id',
            ],
            3 => [
                'payment_method' => 'required_if:pay_now,true|in:cash,card,wallet',
            ],
            default => [],
        };
    }

    public function messages(): array
    {
        return [
            'selected_participant_id.required' => 'يرجى اختيار المشترك',
            'selected_participant_id.exists' => 'المشترك المختار غير موجود',
            'selected_activity_id.required' => 'يرجى اختيار النشاط',
            'selected_activity_id.exists' => 'النشاط المختار غير موجود',
            'selected_program_id.required' => 'يرجى اختيار البرنامج',
            'selected_program_id.exists' => 'البرنامج المختار غير موجود',
            'payment_method.required_if' => 'يرجى اختيار طريقة الدفع',
            'payment_method.in' => 'طريقة الدفع غير صالحة',
        ];
    }

    public function selectParticipant(int $id, string $name): void
    {
        $this->selected_participant_id = $id;
        $this->selected_participant_name = $name;
    }

    public function nextStep(): void
    {
        $this->validate();
        $this->currentStep = min($this->currentStep + 1, $this->totalSteps);
    }

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

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

    public function updatedSelectedActivityId(): void
    {
        $this->selected_program_id = null;
    }

    public function confirm(): void
    {
        try {
            $enrollmentService = app(\App\Domain\Training\Services\EnrollmentService::class);

            $participant = Participant::findOrFail($this->selected_participant_id);
            $program = TrainingProgram::findOrFail($this->selected_program_id);

            $enrollment = $enrollmentService->enrollInProgram(
                $participant,
                $program,
                auth()->user(),
                [
                    'pay_now' => $this->pay_now,
                    'payment_method' => $this->pay_now ? $this->payment_method : null,
                ]
            );

            $this->completed = true;
            $this->currentStep = 4;

            $this->created_participant_uuid = $participant->uuid;
            if ($enrollment->invoice_id) {
                $invoice = \App\Domain\Financial\Models\Invoice::find($enrollment->invoice_id);
                $this->created_invoice_uuid = $invoice?->uuid;
            }

            session()->flash('success', __('تم التسجيل في البرنامج بنجاح'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    #[Computed]
    public function selectedProgramFee(): int
    {
        if (!$this->selected_program_id) {
            return 0;
        }

        $price = BasePrice::where('priceable_type', TrainingProgram::class)
            ->where('priceable_id', $this->selected_program_id)
            ->where('is_active', true)
            ->where('effective_from', '<=', now())
            ->where(fn ($q) => $q->whereNull('effective_to')->orWhere('effective_to', '>=', now()))
            ->forBranch($this->branchId)
            ->orderByDesc('priority')
            ->first();

        return $price?->amount ?? 0;
    }

    #[Computed]
    public function proratedProgramFee(): ProrationResult
    {
        $baseFee = $this->selectedProgramFee;
        $service = app(ProrationService::class);
        if (!$service->isEnabled() || $baseFee === 0) {
            return new ProrationResult(
                applied: false,
                originalAmount: $baseFee,
                proratedAmount: $baseFee,
                remainingDays: 30,
                renewalDay: $service->renewalDay(),
                description: '',
            );
        }
        return $service->calculate($baseFee);
    }

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

        $activities = Activity::where('is_active', true)->orderBy('name_ar')->get();
        $programs = collect();

        if ($this->selected_activity_id && $this->selected_participant_id) {
            // Get programs not already enrolled in
            $enrolledProgramIds = Enrollment::where('participant_id', $this->selected_participant_id)
                ->whereIn('status', ['active', 'pending'])
                ->pluck('training_program_id');

            $programs = TrainingProgram::where('activity_id', $this->selected_activity_id)
                ->where('status', 'active')
                ->whereNotIn('id', $enrolledProgramIds)
                ->whereHas('groups', fn ($q) => $q->where('branch_id', $this->branchId)->whereIn('status', ['active', 'forming']))
                ->orderBy('name_ar')
                ->get();
        }

        return view('livewire.receptionist.enroll-existing-wizard', [
            'searchResults' => $searchResults,
            'activities' => $activities,
            'programs' => $programs,
        ]);
    }
}
