<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\ActivityLog;
use App\Models\Attendance;
use App\Models\PayrollRun;
use App\Models\Payslip;
use App\Models\Staff;
use App\Models\Transaction;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

// E3 — Payroll: attendance-linked salary run + payslips + accounting post.
class PayrollController extends Controller
{
    public function runs()
    {
        return response()->json(['data' => PayrollRun::withCount('payslips')->orderByDesc('period')->get()]);
    }

    public function payslips(PayrollRun $run)
    {
        return response()->json([
            'data' => $run->payslips()->with('staff:id,name,emp_no,designation,type')->get(),
            'run' => $run,
        ]);
    }

    // POST /payroll/run { period: "YYYY-MM" } — compute a full salary run.
    // Deduction rule: absence days in the period × (basic / 26 working days).
    public function run(Request $request)
    {
        $data = $request->validate(['period' => ['required', 'regex:/^\d{4}-\d{2}$/']]);
        $period = $data['period'];

        if (PayrollRun::where('period', $period)->exists()) {
            return response()->json(['message' => "Payroll for {$period} already exists."], 422);
        }

        $staff = Staff::where('status', 'active')->get();
        $run = null;

        DB::transaction(function () use ($staff, $period, $request, &$run) {
            $run = PayrollRun::create([
                'period' => $period,
                'run_date' => now()->toDateString(),
                'status' => 'draft',
                'created_by' => $request->user()?->name,
            ]);

            $gross = $ded = $net = 0;
            foreach ($staff as $s) {
                $basic = (float) ($s->basic_salary ?? 0);
                $absences = Attendance::where('person_type', 'staff')
                    ->where('person_id', $s->id)
                    ->where('date', 'like', "$period%")
                    ->where('status', 'absent')
                    ->count();
                $deduction = round(($basic / 26) * $absences, 2);
                $netAmt = round($basic - $deduction, 2);

                Payslip::create([
                    'payroll_run_id' => $run->id,
                    'staff_id' => $s->id,
                    'basic' => $basic,
                    'absence_days' => $absences,
                    'deductions' => $deduction,
                    'net' => $netAmt,
                ]);
                $gross += $basic;
                $ded += $deduction;
                $net += $netAmt;
            }
            $run->update(['total_gross' => $gross, 'total_deductions' => $ded, 'total_net' => $net]);
        });
        ActivityLog::record('create', 'payroll', "Payroll run {$period} ({$staff->count()} payslips)", $run);

        return response()->json(['data' => $run->fresh()->loadCount('payslips')], 201);
    }

    // POST /payroll/{run}/pay — mark paid and post the expense to accounting.
    public function markPaid(Request $request, PayrollRun $run)
    {
        if ($run->status === 'paid') {
            return response()->json(['message' => 'Already paid.'], 422);
        }
        $run->update(['status' => 'paid']);
        $run->payslips()->update(['status' => 'paid']);

        Transaction::create([
            'branch_id' => $request->header('X-Branch-Id'),
            'type' => 'expense',
            'category' => 'Salaries',
            'amount' => $run->total_net,
            'date' => now()->toDateString(),
            'method' => 'bank',
            'reference' => "PAYROLL-{$run->period}",
            'note' => "Payroll {$run->period}",
            'created_by' => $request->user()?->name,
        ]);
        ActivityLog::record('update', 'payroll', "Payroll {$run->period} disbursed ({$run->total_net})", $run);

        return response()->json(['data' => $run->fresh()]);
    }
}
