<?php

namespace App\Services\Payroll;

use App\Models\Expense;
use App\Models\PrePayment;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Schema;

class PayrollPeriodDeductionService
{
    public function prePaymentAmount(int $userId, int $companyId, int $year, int $month): float
    {
        if (! class_exists(PrePayment::class)) {
            return 0.0;
        }

        $table = (new PrePayment)->getTable();
        if (! Schema::hasTable($table)) {
            return 0.0;
        }

        $query = PrePayment::withoutGlobalScopes()
            ->where('company_id', $companyId)
            ->where('user_id', $userId)
            ->where('year', $year)
            ->where('month', $month)
            ->where('status', PrePayment::STATUS_PENDING);

        return (float) $query->sum('amount');
    }

    public function expenseReimbursementAmount(int $userId, int $companyId, int $year, int $month): float
    {
        return (float) $this->expenseQueryForPeriod($userId, $companyId, $year, $month, false)->sum('amount');
    }

    public function expenseDeductionAmount(int $userId, int $companyId, int $year, int $month): float
    {
        return (float) $this->expenseQueryForPeriod($userId, $companyId, $year, $month, true)->sum('amount');
    }

    protected function expenseQueryForPeriod(
        int $userId,
        int $companyId,
        int $year,
        int $month,
        bool $deductFromPayroll
    ): Builder {
        if (! class_exists(Expense::class)) {
            return Expense::query()->whereRaw('1 = 0');
        }

        $table = (new Expense)->getTable();
        if (! Schema::hasTable($table)) {
            return Expense::query()->whereRaw('1 = 0');
        }

        $query = Expense::withoutGlobalScopes()
            ->where('company_id', $companyId)
            ->where('user_id', $userId)
            ->where('status', 'approved')
            ->whereNull('payroll_cycle_id');

        if (Schema::hasColumn($table, 'date')) {
            $query->whereYear('date', $year)->whereMonth('date', $month);
        } elseif (Schema::hasColumn($table, 'expense_date')) {
            $query->whereYear('expense_date', $year)->whereMonth('expense_date', $month);
        } elseif (Schema::hasColumn($table, 'year') && Schema::hasColumn($table, 'month')) {
            $query->where('year', $year)->where('month', $month);
        } else {
            return Expense::query()->whereRaw('1 = 0');
        }

        if (Schema::hasColumn($table, 'deduct_from_payroll')) {
            $query->where('deduct_from_payroll', $deductFromPayroll);
        } elseif ($deductFromPayroll) {
            return Expense::query()->whereRaw('1 = 0');
        }

        return $query;
    }
}
