<?php

namespace App\Livewire\Studio\Finance;

use App\Enums\SalaryAdjustmentType;
use App\Jobs\StorePushNotification;
use App\Livewire\Forms\Studio\Finance\PayrollForm;
use App\Models\Payroll as PayrollModel;
use App\Models\PayrollAdjustment;
use App\Models\PushNotification;
use App\Models\User;
use App\Traits\Authorization\WithAuthorization;
use App\Traits\Components\WithCloseModal;
use App\Traits\Components\WithConfirmation;
use App\Traits\Components\WithToast;
use App\Traits\Components\WithUserSelector;
use App\Traits\Notification\WithSubscribeNotification;
use App\Traits\Utilities\WithUpdatedData;
use Barryvdh\DomPDF\Facade\Pdf;
use Flux\Flux;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\DB;
use Livewire\Attributes\On;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Title('Penggajian')]
class Payroll extends Component
{
    use WithAuthorization, WithCloseModal, WithConfirmation, WithSubscribeNotification, WithToast, WithUpdatedData, WithUserSelector;

    public PayrollForm $form;

    public string $method = 'create';

    public string $modalTitle = '';

    public array $users = [];

    public function mount(): void
    {
        $this->users = User::whereHas('employee')
            ->withoutDeveloper()
            ->latest()
            ->get()
            ->mapWithKeys(fn ($user) => [
                $user->id => $user->employee->full_name,
            ])
            ->toArray();
    }

    public function create(): void
    {
        $this->canOrAbort('manage adjustment');

        $result = $this->form->store();

        StorePushNotification::dispatch(
            PushNotification::where('user_id', $result['userIds'])->get(),
            [
                'title' => 'Order',
                'body' => $result['message'],
                'url' => route('studio.finance.payroll.index'),
            ],
        );

        $this->dispatch('refreshDatatable');

        $this->toast('Penyesuaian berhasil ditambahkan.');

        Flux::modals()->close();
    }

    public function delete(PayrollAdjustment $adjustment): void
    {
        $this->canOrAbort('manage adjustment');

        DB::transaction(function () use ($adjustment) {
            $payroll = PayrollModel::find($adjustment->payroll_id);

            if ($adjustment->type->value == SalaryAdjustmentType::BONUS->value) {
                $payroll->bonus -= $adjustment->amount;
            } elseif ($adjustment->type->value == SalaryAdjustmentType::DEDUCTION->value) {
                $payroll->deduction -= $adjustment->amount;
            }

            $payroll->total_salary = $payroll->base_salary + $payroll->bonus - $payroll->deduction;

            $payroll->save();

            $adjustment->delete();
        });

        $this->dispatch('refreshDatatable');
        $this->toast('Penggajian berhasil dihapus.');
        Flux::modals()->close();
    }

    #[On('fn:exportPdf')]
    public function exportPdf(PayrollModel $payroll)
    {
        $this->canOrAbort('view payroll');

        // Only owner and developer can export payroll
        $user = auth()->user();
        if (! $user->hasRole(['Owner', 'Developer']) && $payroll->user_id !== $user->id) {
            abort(403, 'Anda tidak memiliki akses untuk melihat payroll ini.');
        }

        $payroll->load(['user.employee', 'adjustments']);

        $pdf = Pdf::loadView('pdf.payroll-slip', [
            'payroll' => $payroll,
        ]);

        $period = $period = $payroll->period_month.'-01';
        $fileName = 'Gaji '
            .$payroll->user->employee->full_name
            .' Bulan '
            .formatDateLocalized($period, 'F Y')
            .'.pdf';

        return response()->streamDownload(function () use ($pdf) {
            echo $pdf->download();
        }, $fileName);
    }

    #[On('modal:open')]
    public function openModal(string $method, string $modalTitle, ?string $id = null): void
    {
        $this->resetValidation();
        $this->resetErrorBag();

        $this->method = $method;
        $this->modalTitle = $modalTitle;
    }

    public function render(): View
    {
        $payrolls = PayrollModel::with(['user', 'user.employee'])
            ->notPaid()
            ->when(! auth()->user()->hasRole(['Owner', 'Developer']), function ($query) {
                return $query->where('payrolls.user_id', auth()->id());
            })
            ->where('period_month', now()->format('Y-m'))
            ->whereHas('user', function ($query) {
                $query->active()
                    ->withoutDeveloper();
            })
            ->get();

        return view('livewire.studio.finance.payrolls', [
            'pageTitle' => 'Penggajian',
            'payrolls' => $payrolls,
        ]);
    }
}
