<?php

namespace App\Livewire\Receptionist;

use App\Domain\Financial\Enums\InvoiceStatus;
use App\Domain\Financial\Models\Invoice;
use App\Domain\Financial\Services\InvoiceService;
use App\Domain\Financial\Services\PaymentService;
use App\Domain\Identity\Models\Branch;
use App\Domain\Participant\Models\Participant;
use App\Domain\Pricing\Services\PricingService;
use App\Domain\Shared\Exceptions\DomainException;
use App\Domain\Shared\Services\PlatformFeeService;
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Domain\Training\Models\Activity;
use App\Domain\Training\Models\TrainingProgram;
use App\Domain\Training\Services\EnrollmentService;
use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Layout('layouts.app')]
#[Title('تسجيل لاعب سابق')]
class RetroactiveEnrollmentWizard extends Component
{
    use UsesBranchScope;

    public ?int $branchId = null;

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

    // Step 1: Search existing participant
    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: Retroactive dates + months owed
    public string $actual_start_date = '';
    public array $monthStatuses = []; // ['2026-05' => 'unpaid', '2026-06' => 'paid_outside', ...]

    // Admin override
    public bool $priceOverrideEnabled = false;
    public string $priceOverrideInput = '';
    public string $priceOverrideReason = '';

    // Step 4: Payment for outstanding months
    public bool $pay_now = false;
    public string $payment_method = 'cash';
    public string $payment_notes = '';

    // Result
    public bool $completed = false;
    public ?string $enrollment_summary = null;
    public int $invoices_created = 0;
    public int $payments_recorded = 0;
    public ?string $participant_uuid = null;

    public function mount(): void
    {
        $this->authorize('enrollments.create');
        $this->branchId = $this->getActiveBranchId() ?? Branch::where('is_active', true)->first()?->id;
    }

    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 => ['actual_start_date' => 'required|date|before_or_equal:today'],
            4 => ['payment_method' => 'required_if:pay_now,true|in:cash,card,bank_transfer,wallet,online,cheque,other'],
            default => [],
        };
    }

    public function messages(): array
    {
        return [
            'selected_participant_id.required' => 'يرجى اختيار المشترك',
            'selected_activity_id.required' => 'يرجى اختيار النشاط',
            'selected_program_id.required' => 'يرجى اختيار البرنامج',
            'actual_start_date.required' => 'يرجى تحديد تاريخ البدء الفعلي',
            'actual_start_date.before_or_equal' => 'تاريخ البدء لا يمكن أن يكون في المستقبل',
        ];
    }

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

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

    public function updatedActualStartDate(): void
    {
        $this->calculateMonthsOwed();
    }

    public function calculateMonthsOwed(): void
    {
        if (!$this->actual_start_date || !$this->selected_program_id) {
            $this->monthStatuses = [];
            return;
        }

        $start = Carbon::parse($this->actual_start_date)->startOfMonth();
        $now = now()->startOfMonth();

        $months = [];
        $current = $start->copy();
        while ($current->lte($now)) {
            $key = $current->format('Y-m');
            $months[$key] = 'unpaid';
            $current->addMonth();
        }

        // Preserve existing selections
        foreach ($months as $key => $default) {
            if (!isset($this->monthStatuses[$key])) {
                $this->monthStatuses[$key] = $default;
            }
        }

        // Remove months that are no longer in range
        $this->monthStatuses = array_intersect_key($this->monthStatuses, $months);
    }

    public function setMonthStatus(string $month, string $status): void
    {
        if (isset($this->monthStatuses[$month])) {
            $this->monthStatuses[$month] = $status;
        }
    }

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

        try {
            $participant = Participant::find($this->selected_participant_id);
            $program = TrainingProgram::find($this->selected_program_id);
            if (!$participant || !$program) return 0;

            $pricingService = app(PricingService::class);
            $result = $pricingService->calculate(
                priceable: $program,
                participant: $participant,
                branchId: $this->branchId,
            );
            return $result->finalAmount;
        } catch (\Throwable) {
            return 0;
        }
    }

    #[Computed]
    public function unpaidMonthsCount(): int
    {
        return collect($this->monthStatuses)->filter(fn ($s) => $s === 'unpaid')->count();
    }

    #[Computed]
    public function totalOwed(): int
    {
        if ($this->priceOverrideEnabled && $this->priceOverrideInput !== '') {
            return max(0, (int) round((float) $this->priceOverrideInput * 100));
        }
        return $this->monthlyPrice * $this->unpaidMonthsCount;
    }

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

        if ($this->currentStep === 2) {
            $this->calculateMonthsOwed();
        }

        $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 confirm(): void
    {
        $actor = auth()->user();

        try {
            DB::transaction(function () use ($actor) {
                $participant = Participant::findOrFail($this->selected_participant_id);
                $program = TrainingProgram::findOrFail($this->selected_program_id);
                $enrollmentService = app(EnrollmentService::class);
                $invoiceService = app(InvoiceService::class);
                $paymentService = app(PaymentService::class);

                // 1. Create enrollment with retroactive start date
                $enrollment = $enrollmentService->enrollInProgram(
                    $participant,
                    $program,
                    $actor,
                    [
                        'start_date' => $this->actual_start_date,
                        'payment_status' => 'pending',
                    ]
                );

                // 2. Calculate effective per-month price
                $perMonth = $this->monthlyPrice;

                // Admin override distributes total evenly
                $unpaidCount = $this->unpaidMonthsCount;
                $overrideActive = $this->priceOverrideEnabled && $this->priceOverrideInput !== '' && $actor->is_super_admin;
                if ($overrideActive && $unpaidCount > 0) {
                    $overrideTotal = max(0, (int) round((float) $this->priceOverrideInput * 100));
                    $perMonth = (int) floor($overrideTotal / $unpaidCount);

                    Log::channel('audit')->info('retroactive_enrollment_price_override', [
                        'actor_id' => $actor->id,
                        'actor_name' => $actor->name,
                        'participant_name' => $this->selected_participant_name,
                        'program' => $program->name_ar,
                        'original_per_month' => $this->monthlyPrice,
                        'override_total' => $overrideTotal,
                        'effective_per_month' => $perMonth,
                        'months_count' => $unpaidCount,
                        'reason' => $this->priceOverrideReason,
                    ]);
                }

                // 3. Generate invoices per month (no platform fee on individual past invoices)
                $invoicesCreated = 0;
                $paymentsRecorded = 0;
                $totalRetroactiveRevenue = 0;

                foreach ($this->monthStatuses as $monthKey => $status) {
                    $monthDate = Carbon::parse($monthKey . '-01');

                    if ($status === 'paid_outside') {
                        $invoice = $invoiceService->create([
                            'academy_id' => $participant->academy_id,
                            'branch_id' => $this->branchId,
                            'billable_type' => $participant->getMorphClass(),
                            'billable_id' => $participant->id,
                            'total_amount' => $perMonth,
                            'subtotal_amount' => $perMonth,
                            'discount_amount' => 0,
                            'tax_amount' => 0,
                            'service_fee_amount' => 0,
                            'due_date' => $monthDate->copy()->addDays(7)->toDateString(),
                            'contact_name' => $participant->person?->name_ar,
                            'notes' => 'اشتراك ' . $program->name_ar . ' — ' . $this->getArabicMonth($monthDate),
                            'metadata' => ['retroactive' => true, 'month' => $monthKey, 'fee_deferred_to_registration_month' => true],
                        ], [
                            [
                                'description' => 'اشتراك: ' . $program->name_ar . ' (' . $this->getArabicMonth($monthDate) . ')',
                                'quantity' => 1,
                                'unit_price' => $perMonth,
                                'discount_amount' => 0,
                                'tax_amount' => 0,
                            ],
                        ], $actor);

                        $invoice->update([
                            'status' => InvoiceStatus::Paid,
                            'paid_amount' => $perMonth,
                            'due_amount' => 0,
                            'paid_at' => $monthDate->copy()->addDays(1),
                            'metadata' => array_merge($invoice->metadata ?? [], [
                                'paid_outside_system' => true,
                                'recorded_by' => $actor->name,
                                'recorded_at' => now()->toIso8601String(),
                            ]),
                        ]);

                        $totalRetroactiveRevenue += $perMonth;
                        $invoicesCreated++;
                    } elseif ($status === 'unpaid') {
                        $invoice = $invoiceService->create([
                            'academy_id' => $participant->academy_id,
                            'branch_id' => $this->branchId,
                            'billable_type' => $participant->getMorphClass(),
                            'billable_id' => $participant->id,
                            'total_amount' => $perMonth,
                            'subtotal_amount' => $perMonth,
                            'discount_amount' => 0,
                            'tax_amount' => 0,
                            'service_fee_amount' => 0,
                            'due_date' => $monthDate->copy()->addDays(7)->toDateString(),
                            'contact_name' => $participant->person?->name_ar,
                            'notes' => 'اشتراك ' . $program->name_ar . ' — ' . $this->getArabicMonth($monthDate),
                            'metadata' => ['retroactive' => true, 'month' => $monthKey, 'fee_deferred_to_registration_month' => true],
                        ], [
                            [
                                'description' => 'اشتراك: ' . $program->name_ar . ' (' . $this->getArabicMonth($monthDate) . ')',
                                'quantity' => 1,
                                'unit_price' => $perMonth,
                                'discount_amount' => 0,
                                'tax_amount' => 0,
                            ],
                        ], $actor);

                        $invoice->update(['status' => InvoiceStatus::Sent]);
                        $totalRetroactiveRevenue += $perMonth;
                        $invoicesCreated++;

                        if ($this->pay_now && $perMonth > 0) {
                            $paymentService->recordPayment([
                                'invoice_id' => $invoice->id,
                                'branch_id' => $this->branchId,
                                'amount' => $perMonth,
                                'method' => $this->payment_method,
                                'direction' => 'inbound',
                                'currency' => 'EGP',
                                'payment_date' => now()->toDateString(),
                                'notes' => 'دفع بأثر رجعي — ' . $this->getArabicMonth($monthDate),
                            ], $actor);
                            $paymentsRecorded++;
                        }
                    }
                }

                // 4. Platform fee invoice — charged TODAY for ALL retroactive months
                $platformFeeService = app(PlatformFeeService::class);
                if ($platformFeeService->isActive() && $totalRetroactiveRevenue > 0) {
                    $totalPlatformFee = $platformFeeService->calculate($totalRetroactiveRevenue);

                    if ($totalPlatformFee > 0) {
                        $monthCount = count($this->monthStatuses);
                        $feeInvoice = $invoiceService->create([
                            'academy_id' => $participant->academy_id,
                            'branch_id' => $this->branchId,
                            'billable_type' => $participant->getMorphClass(),
                            'billable_id' => $participant->id,
                            'total_amount' => $totalPlatformFee,
                            'subtotal_amount' => 0,
                            'discount_amount' => 0,
                            'tax_amount' => 0,
                            'service_fee_amount' => $totalPlatformFee,
                            'due_date' => now()->addDays(7)->toDateString(),
                            'contact_name' => $participant->person?->name_ar,
                            'notes' => 'رسوم خدمة — تسجيل بأثر رجعي (' . $monthCount . ' شهور) — ' . $program->name_ar,
                            'metadata' => [
                                'retroactive_platform_fee' => true,
                                'covers_months' => array_keys($this->monthStatuses),
                                'total_revenue_base' => $totalRetroactiveRevenue,
                                'fee_percentage' => $platformFeeService->getPercentage(),
                                'registered_at' => now()->toIso8601String(),
                            ],
                        ], [
                            [
                                'description' => 'رسوم خدمة المنصة — تسجيل بأثر رجعي (' . $monthCount . ' شهور)',
                                'quantity' => 1,
                                'unit_price' => $totalPlatformFee,
                                'discount_amount' => 0,
                                'tax_amount' => 0,
                            ],
                        ], $actor);

                        $feeInvoice->update(['status' => InvoiceStatus::Sent]);
                        $invoicesCreated++;
                    }
                }

                // 5. Set next_billing_date to 1st of next month
                $enrollment->update([
                    'next_billing_date' => now()->addMonth()->startOfMonth()->toDateString(),
                    'last_billed_at' => now()->toDateString(),
                ]);

                $this->invoices_created = $invoicesCreated;
                $this->payments_recorded = $paymentsRecorded;
                $this->participant_uuid = $participant->uuid;
                $this->enrollment_summary = $program->name_ar;
                $this->completed = true;
                $this->currentStep = 5;
            });

            session()->flash('success', __('تم تسجيل اللاعب بنجاح بأثر رجعي'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        } catch (\Throwable $e) {
            Log::error('Retroactive enrollment failed', ['error' => $e->getMessage(), 'trace' => $e->getTraceAsString()]);
            session()->flash('error', __('حدث خطأ غير متوقع'));
        }
    }

    public function render()
    {
        $searchResults = collect();
        if (strlen($this->search) >= 2 && !$this->selected_participant_id) {
            $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}%");
                      });
                })
                ->limit(10)
                ->get();
        }

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

        $programs = collect();
        if ($this->selected_activity_id) {
            $programs = TrainingProgram::where('activity_id', $this->selected_activity_id)
                ->where('status', 'active')
                ->where('registration_open', true)
                ->orderBy('name_ar')
                ->get();
        }

        return view('livewire.receptionist.retroactive-enrollment-wizard', [
            'searchResults' => $searchResults,
            'activities' => $activities,
            'programs' => $programs,
            'isSuperAdmin' => auth()->user()?->is_super_admin ?? false,
        ]);
    }

    private function getArabicMonth(Carbon $date): string
    {
        $months = [
            1 => 'يناير', 2 => 'فبراير', 3 => 'مارس', 4 => 'أبريل',
            5 => 'مايو', 6 => 'يونيو', 7 => 'يوليو', 8 => 'أغسطس',
            9 => 'سبتمبر', 10 => 'أكتوبر', 11 => 'نوفمبر', 12 => 'ديسمبر',
        ];
        return $months[$date->month] . ' ' . $date->year;
    }
}
