<?php

namespace App\Modules\Payroll\Services;

use App\Modules\Payroll\Models\PayrollEmployeeSnapshot;
use App\Modules\Payroll\Repositories\PayrollAdjustmentRepository;
use App\Modules\Payroll\Repositories\PayrollEmployeeSnapshotRepository;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

final class PayslipViewService
{
    public function __construct(
        private readonly PayrollEmployeeSnapshotRepository $snapshots,
        private readonly PayrollAdjustmentRepository $adjustments,
    ) {}

    public function listForEmployee(int $tenantId, int $employeeId): LengthAwarePaginator
    {
        return $this->snapshots->paginateFinalizedForEmployee($tenantId, $employeeId);
    }

    public function buildEmployeePayslip(int $tenantId, int $employeeId, int $snapshotId): PayrollEmployeeSnapshot
    {
        $snap = $this->snapshots->findFinalizedForTenantEmployee($tenantId, $employeeId, $snapshotId);
        abort_if($snap === null, 404);

        return $snap;
    }

    public function buildAdminPayslip(int $tenantId, int $snapshotId): PayrollEmployeeSnapshot
    {
        $snap = $this->snapshots->findForTenant($tenantId, $snapshotId);
        abort_if($snap === null, 404);
        abort_if($snap->period?->isFinalized() !== true, 404);

        return $snap;
    }

    /**
     * @return array{
     *   base_salary: string,
     *   overtime: array{minutes: int, amount: ?string},
     *   leave: array{days: string, amount: ?string},
     *   adjustments: array{total: string, items: array<int, array{type: string, amount: string, reason: ?string}>},
     *   gross_amount: ?string
     * }
     */
    public function breakdown(PayrollEmployeeSnapshot $snapshot): array
    {
        $items = $this->adjustments->listForEmployeePeriod(
            (int) $snapshot->tenant_id,
            (int) $snapshot->employee_id,
            (int) $snapshot->payroll_period_id,
        )->map(fn ($a) => [
            'type' => (string) $a->type,
            'amount' => (string) $a->amount,
            'reason' => $a->reason,
        ])->all();

        return [
            'base_salary' => (string) $snapshot->base_salary,
            'overtime' => [
                'minutes' => (int) $snapshot->overtime_minutes,
                'amount' => data_get($snapshot->snapshot_data, 'overtime_amount'),
            ],
            'leave' => [
                'days' => (string) $snapshot->leave_days,
                'amount' => data_get($snapshot->snapshot_data, 'leave_deduction_amount'),
            ],
            'adjustments' => [
                'total' => (string) $snapshot->adjustments_total,
                'items' => $items,
            ],
            'gross_amount' => $snapshot->gross_amount !== null ? (string) $snapshot->gross_amount : null,
        ];
    }
}

