<?php

namespace App\Livewire\HR;

use App\Domain\HR\Enums\PayrollPeriodStatus;
use App\Domain\HR\Enums\PayslipStatus;
use App\Domain\HR\Models\PayrollPeriod;
use App\Domain\HR\Models\Payslip;
use App\Domain\HR\Models\Trainer;
use App\Domain\HR\Services\PayrollService;
use App\Domain\Shared\Traits\UsesBranchScope;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;

#[Layout('layouts.app')]
#[Title('إدارة الرواتب')]
class PayrollDashboard extends Component
{
    use WithPagination, UsesBranchScope;

    #[Url]
    public string $periodFilter = '';

    #[Url]
    public string $payslipStatus = '';

    #[Url]
    public string $search = '';

    #[Url]
    public string $activeTab = 'periods'; // periods | payslips

    // Stats
    public bool $payrollEnabled = false;
    public int $totalPayrollThisMonth = 0;
    public int $pendingApprovals = 0;
    public int $paidThisMonth = 0;
    public int $activeTrainers = 0;

    // Mark-paid modal state
    public bool $showMarkPaidModal = false;

    // Set by openMarkPaidModal() only. Without the lock the browser could point
    // confirmMarkPaid() at any payslip id without ever opening the modal.
    #[Locked]
    public ?int $markPaidPayslipId = null;
    public string $markPaidMethod = 'cash';
    public string $markPaidReference = '';

    public function mount(): void
    {
        $this->authorize('payroll.manage');
        $this->loadStats();
    }

    public function updatedSearch(): void
    {
        $this->resetPage();
    }

    public function updatedPeriodFilter(): void
    {
        $this->resetPage();
    }

    public function updatedPayslipStatus(): void
    {
        $this->resetPage();
    }

    public function loadStats(): void
    {
        $academyId = app('current_academy')->id;

        $this->payrollEnabled = (bool) app(\App\Domain\Shared\Services\SettingsService::class)->get('payroll_enabled', false);

        $currentPeriod = PayrollPeriod::where('academy_id', $academyId)
            ->latest('period_start')
            ->first();

        // payroll_periods has no branch — a period covers the academy — so its
        // total_net is the whole academy's payroll and reading it here put an
        // every-branch figure beside three branch-figures. Sum the period's
        // payslips instead; Payslip carries BranchScope, so this is the active
        // branch's share of that same period.
        $this->totalPayrollThisMonth = $currentPeriod
            ? (int) Payslip::where('academy_id', $academyId)
                ->where('payroll_period_id', $currentPeriod->id)
                ->whereNot('status', PayslipStatus::Cancelled->value)
                ->sum('net_amount')
            : 0;

        // No branch clause below: Payslip and Trainer both carry BranchScope.
        // The whereHas('trainer.employee') these used to carry was not only
        // redundant, it dropped every payslip of a freelance coach with no
        // employee row.
        $this->pendingApprovals = Payslip::where('academy_id', $academyId)
            ->whereIn('status', [
                PayslipStatus::Draft->value,
                PayslipStatus::PendingApproval->value,
            ])
            ->count();

        $this->paidThisMonth = Payslip::where('academy_id', $academyId)
            ->where('status', PayslipStatus::Paid->value)
            ->whereMonth('paid_at', now()->month)
            ->whereYear('paid_at', now()->year)
            ->sum('net_amount');

        $this->activeTrainers = Trainer::where('academy_id', $academyId)
            ->where('status', 'active')
            ->count();
    }

    public function enablePayroll(): void
    {
        app(\App\Domain\Shared\Services\SettingsService::class)->set('payroll_enabled', '1');
        app(\App\Domain\Shared\Services\SettingsService::class)->set('auto_trainer_compensation_enabled', '1');
        $this->payrollEnabled = true;
        session()->flash('success', __('تم تفعيل نظام الرواتب'));
        $this->loadStats();
    }

    public function createPeriod(): void
    {
        try {
            $service = app(PayrollService::class);
            $service->getOrCreateCurrentPeriod(
                app('current_academy')->id,
                auth()->user()
            );
            session()->flash('success', __('تم إنشاء فترة الرواتب بنجاح'));
            $this->loadStats();
        } catch (\Throwable $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function calculatePeriod(int $periodId): void
    {
        try {
            $period = PayrollPeriod::findOrFail($periodId);
            $service = app(PayrollService::class);
            $service->calculatePeriod($period, auth()->user());
            session()->flash('success', __('تم احتساب كشوف الرواتب بنجاح'));
            $this->loadStats();
        } catch (\Throwable $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function approvePeriod(int $periodId): void
    {
        try {
            $period = PayrollPeriod::findOrFail($periodId);
            $service = app(PayrollService::class);
            $service->approvePeriod($period, auth()->user());
            session()->flash('success', __('تم اعتماد فترة الرواتب'));
            $this->loadStats();
        } catch (\Throwable $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function closePeriod(int $periodId): void
    {
        try {
            $period = PayrollPeriod::findOrFail($periodId);
            $service = app(PayrollService::class);
            $service->closePeriod($period, auth()->user());
            session()->flash('success', __('تم إغلاق فترة الرواتب'));
            $this->loadStats();
        } catch (\Throwable $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function approvePayslip(int $payslipId): void
    {
        try {
            $payslip = Payslip::findOrFail($payslipId);
            $service = app(PayrollService::class);
            $service->approvePayslip($payslip, auth()->user());
            session()->flash('success', __('تم اعتماد كشف الراتب'));
            $this->loadStats();
        } catch (\Throwable $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function openMarkPaidModal(int $payslipId): void
    {
        $this->markPaidPayslipId = $payslipId;
        $this->markPaidMethod = 'cash';
        $this->markPaidReference = '';
        $this->showMarkPaidModal = true;
    }

    public function confirmMarkPaid(): void
    {
        if (!$this->markPaidPayslipId) {
            return;
        }

        try {
            $payslip = Payslip::findOrFail($this->markPaidPayslipId);
            $service = app(PayrollService::class);
            $service->markPaid(
                $payslip,
                $this->markPaidMethod,
                $this->markPaidReference ?: null,
                auth()->user()
            );
            $this->showMarkPaidModal = false;
            $this->markPaidPayslipId = null;
            session()->flash('success', __('تم تسجيل الدفع بنجاح'));
            $this->loadStats();
        } catch (\Throwable $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function closeModal(): void
    {
        $this->showMarkPaidModal = false;
        $this->markPaidPayslipId = null;
    }

    public function render()
    {
        // Deliberately academy-wide: a payroll period is an academy-level object
        // with no branch of its own, and its totals cover every branch. The view
        // labels the table as such so the figures are not read as this branch's.
        $periodsQuery = PayrollPeriod::where('academy_id', app('current_academy')->id)
            ->latest('period_start');

        if ($this->periodFilter) {
            $periodsQuery->where('status', $this->periodFilter);
        }

        // Branch-filtered by Payslip's own BranchScope.
        $payslipsQuery = Payslip::with(['trainer.employee.person', 'trainer.person', 'period'])
            ->where('academy_id', app('current_academy')->id)
            ->latest();

        if ($this->payslipStatus) {
            $payslipsQuery->where('status', $this->payslipStatus);
        }

        if ($this->search) {
            $search = $this->search;
            $payslipsQuery->whereHas('trainer.employee.person', function ($q) use ($search) {
                $q->where('name_ar', 'ilike', "%{$search}%")
                    ->orWhere('name', 'ilike', "%{$search}%");
            });
        }

        return view('livewire.hr.payroll-dashboard', [
            'periods'         => $periodsQuery->paginate(10, pageName: 'periodsPage'),
            'payslips'        => $payslipsQuery->paginate(15, pageName: 'payslipsPage'),
            'periodStatuses'  => PayrollPeriodStatus::cases(),
            'payslipStatuses' => PayslipStatus::cases(),
            'paymentMethods'  => \App\Domain\HR\Enums\StaffPaymentMethod::cases(),
        ]);
    }
}
