<?php

namespace App\Livewire\Participants;

use App\Domain\Attendance\Enums\AttendanceStatus;
use App\Domain\Attendance\Models\AttendanceRecord;
use App\Domain\Financial\Models\Payment;
use App\Domain\Financial\Models\Wallet;
use App\Domain\Financial\Services\RefundService;
use App\Domain\Participant\Models\Participant;
use App\Domain\Participant\Services\ParticipantService;
use App\Domain\Shared\Exceptions\DomainException;
use App\Domain\Training\Services\EnrollmentService;
use App\Domain\Training\Models\Enrollment;
use Illuminate\Support\Facades\DB;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Layout('layouts.app')]
#[Title('ملف المشترك')]
class ParticipantShow extends Component
{
    public Participant $participant;
    public string $activeTab = 'info';

    // Status change modal
    public bool $showStatusModal = false;
    public string $newStatus = '';
    public string $statusReason = '';

    // Refund flow
    public array $selectedPaymentUuids = [];
    public bool $showRefundModal = false;
    public string $refundReason = '';
    public array $refundPreview = [];  // from RefundService::preview()

    public function mount(Participant $participant): void
    {
        $this->participant = $participant->load(['person', 'primaryActivity', 'primaryGuardian', 'guardians', 'creator']);
    }

    public function openStatusModal(string $status): void
    {
        $this->newStatus = $status;
        $this->statusReason = '';
        $this->showStatusModal = true;
    }

    public function closeStatusModal(): void
    {
        $this->showStatusModal = false;
        $this->newStatus = '';
        $this->statusReason = '';
    }

    public function changeStatus(ParticipantService $service): void
    {
        $this->validate([
            'statusReason' => 'required|string|min:3',
        ], [
            'statusReason.required' => 'سبب تغيير الحالة مطلوب',
            'statusReason.min' => 'السبب يجب أن يكون 3 أحرف على الأقل',
        ]);

        try {
            $service->changeStatus($this->participant, $this->newStatus, $this->statusReason, auth()->user());
            $this->participant = $this->participant->fresh(['person', 'primaryActivity', 'primaryGuardian', 'guardians', 'creator']);
            $this->showStatusModal = false;
            $this->newStatus = '';
            $this->statusReason = '';
            session()->flash('success', __('تم تغيير حالة المشترك بنجاح'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function togglePaymentSelection(string $uuid): void
    {
        if (in_array($uuid, $this->selectedPaymentUuids)) {
            $this->selectedPaymentUuids = array_values(
                array_filter($this->selectedPaymentUuids, fn ($u) => $u !== $uuid)
            );
        } else {
            if (count($this->selectedPaymentUuids) >= 2) {
                $this->addError('refund', 'يمكن اختيار دفعتين كحد أقصى');
                return;
            }
            $this->selectedPaymentUuids[] = $uuid;
        }
        $this->resetErrorBag('refund');
    }

    public function openRefundModal(RefundService $service): void
    {
        abort_unless(auth()->user()->is_super_admin || auth()->user()->hasPermission('payments.refund'), 403);

        if (empty($this->selectedPaymentUuids)) {
            $this->addError('refund', 'اختر دفعة واحدة على الأقل للاسترداد');
            return;
        }

        $this->refundPreview = $service->preview($this->selectedPaymentUuids);
        $this->refundReason  = '';
        $this->showRefundModal = true;
    }

    public function closeRefundModal(): void
    {
        $this->showRefundModal  = false;
        $this->refundPreview    = [];
        $this->refundReason     = '';
    }

    public function confirmRefund(RefundService $refundService, EnrollmentService $enrollmentService): void
    {
        abort_unless(auth()->user()->is_super_admin || auth()->user()->hasPermission('payments.refund'), 403);

        $this->validate([
            'refundReason' => 'required|string|min:3|max:500',
        ], [
            'refundReason.required' => 'سبب الاسترداد مطلوب',
            'refundReason.min'      => 'السبب يجب أن يكون 3 أحرف على الأقل',
        ]);

        try {
            DB::transaction(function () use ($refundService, $enrollmentService) {
                $results = $refundService->processRefunds(
                    $this->selectedPaymentUuids,
                    $this->refundReason,
                    auth()->user()
                );

                foreach ($results as $result) {
                    if ($result['enrollment'] instanceof Enrollment) {
                        $enrollmentService->cancel(
                            $result['enrollment'],
                            'استرداد: ' . $this->refundReason,
                            auth()->user()
                        );
                    }
                }
            });

            $this->selectedPaymentUuids = [];
            $this->showRefundModal      = false;
            $this->refundPreview        = [];
            $this->refundReason         = '';

            session()->flash('success', __('تم الاسترداد بنجاح'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
            $this->showRefundModal = false;
        } catch (\Exception $e) {
            session()->flash('error', __('حدث خطأ أثناء الاسترداد، يرجى المحاولة مجدداً'));
            $this->showRefundModal = false;
        }
    }

    public function render()
    {
        $currentStatus = $this->participant->status->value ?? $this->participant->status;

        $validTransitions = match ($currentStatus) {
            'registered' => ['active', 'withdrawn'],
            'active' => ['frozen', 'suspended', 'inactive', 'graduated', 'withdrawn'],
            'frozen' => ['active', 'withdrawn', 'inactive'],
            'suspended' => ['active', 'withdrawn'],
            'inactive' => ['active', 'withdrawn'],
            'graduated' => ['active'],
            'withdrawn' => ['active'],
            default => [],
        };

        $statusLabels = [
            'registered' => 'مسجل',
            'active' => 'نشط',
            'frozen' => 'مجمد',
            'suspended' => 'موقوف',
            'inactive' => 'غير نشط',
            'graduated' => 'متخرج',
            'transferred' => 'محول',
            'withdrawn' => 'منسحب',
            'blacklisted' => 'محظور',
        ];

        // Attendance summary
        $participantClass = \App\Domain\Participant\Models\Participant::class;
        $attendanceQuery = AttendanceRecord::where('subject_type', $participantClass)
            ->where('subject_id', $this->participant->id);

        $totalSessions = (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();
        $cancelledExempt = (clone $attendanceQuery)->whereIn('status', [AttendanceStatus::Cancelled, AttendanceStatus::Exempt])->count();

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

        // Payment history (last 10)
        $recentPayments = Payment::where('payer_type', $participantClass)
            ->where('payer_id', $this->participant->id)
            ->orderByDesc('payment_date')
            ->limit(10)
            ->get();

        // Active enrollments with group and program details
        $activeEnrollments = Enrollment::where('participant_id', $this->participant->id)
            ->where('status', 'active')
            ->with(['group.headTrainer', 'group.schedules', 'program'])
            ->get();

        // Wallet balance
        $wallet = Wallet::where('owner_type', $participantClass)
            ->where('owner_id', $this->participant->id)
            ->first();

        return view('livewire.participants.participant-show', [
            'validTransitions' => $validTransitions,
            'statusLabels' => $statusLabels,
            'totalSessions' => $totalSessions,
            'presentCount' => $presentCount,
            'lateCount' => $lateCount,
            'absentCount' => $absentCount,
            'partialCount' => $partialCount,
            'attendanceRate' => $attendanceRate,
            'recentPayments' => $recentPayments,
            'activeEnrollments' => $activeEnrollments,
            'wallet' => $wallet,
        ]);
    }
}
