<?php

namespace App\Services;

use App\Models\User;
use App\Models\SalaryHistory;
use Carbon\Carbon;

class PayrollService
{
    public function updateStaffSalary(User $user, array $data)
    {
        return $user->update([
            'monthly_salary' => $data['monthly_salary'],
            'bank_name' => $data['bank_name'] ?? null,
            'account_number' => $data['account_number'] ?? null,
            'account_name' => $data['account_name'] ?? null,
            'tax_id' => $data['tax_id'] ?? null,
            'payment_day' => $data['payment_day'] ?? 31,
        ]);
    }

    public function generateSalaryHistory(User $user, $month, $year)
    {
        return SalaryHistory::updateOrCreate(
            [
                'user_id' => $user->id,
                'month' => $month,
                'year' => $year,
            ],
            [
                'monthly_salary' => $user->monthly_salary ?? 0,
                'net_salary' => $user->monthly_salary ?? 0,
                'status' => 'pending',
            ]
        );
    }

    public function addSalaryAdjustment(SalaryHistory $salaryHistory, $type, $amount, $reason = null)
    {
        $adjustment = $salaryHistory->adjustments()->create([
            'type' => $type,
            'amount' => $amount,
            'reason' => $reason,
        ]);

        $salaryHistory->updateNetSalary();
        return $adjustment;
    }

    public function markSalaryAsPaid(SalaryHistory $salaryHistory)
    {
        return $salaryHistory->update([
            'status' => 'paid',
            'paid_at' => now(),
        ]);
    }

    public function getStaffWithSalaries()
    {
        return User::whereHas('roles')
            ->whereNotNull('monthly_salary')
            ->with(['roles', 'latestSalaryHistory'])
            ->get();
    }

    public function getSalaryHistoryForUser(User $user, $perPage = 12)
    {
        return $user->salaryHistories()
            ->with('adjustments')
            ->orderByRaw('year DESC, FIELD(month, "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December")')
            ->paginate($perPage);
    }

    public function generateMonthlyPayroll($month, $year)
    {
        $staff = User::whereHas('roles')
            ->whereNotNull('monthly_salary')
            ->whereDoesntHave('salaryHistories', function ($query) use ($month, $year) {
                $query->where('month', $month)->where('year', $year);
            })
            ->get();

        $generated = 0;
        foreach ($staff as $user) {
            $this->generateSalaryHistory($user, $month, $year);
            $generated++;
        }

        return $generated;
    }

    public function resetPayrollEntries($month, $year)
    {
        $salaryHistories = SalaryHistory::where('month', $month)
            ->where('year', $year)
            ->where('status', '!=', 'paid')
            ->get();

        $updated = 0;
        foreach ($salaryHistories as $salaryHistory) {
            $salaryHistory->adjustments()->delete();
            $salaryHistory->update([
                'net_salary' => $salaryHistory->monthly_salary,
                'status' => 'pending'
            ]);
            $updated++;
        }

        return $updated;
    }

    public function markSalaryAsRefunded(SalaryHistory $salaryHistory)
    {
        return $salaryHistory->update([
            'status' => 'refunded',
            'paid_at' => null,
        ]);
    }

    public function getPayrollData($month, $year)
    {
        return SalaryHistory::with('user')
            ->where('month', $month)
            ->where('year', $year)
            ->orderBy('user_id')
            ->get();
    }
}