<?php

namespace App\Services;

use App\Models\Tenant\EmployeeProfile;
use App\Models\Tenant\PayrollAdjustment;
use App\Models\Tenant\PayrollRun;
use App\Models\Tenant\WorkOrderPart;
use App\Models\Tenant\WorkOrderWork;
use Carbon\Carbon;

class PayrollCalculator
{
    /**
     * Compute (or upsert) the payroll run for a given user + month.
     * Period format: YYYY-MM.
     */
    public function compute(int $userId, string $period, bool $persist = true): PayrollRun
    {
        $start = Carbon::createFromFormat('Y-m', $period)->startOfMonth();
        $end = (clone $start)->endOfMonth();

        $profile = EmployeeProfile::where('user_id', $userId)->first();
        $base = (float) ($profile?->base_salary ?? 0);
        $worksPct = (float) ($profile?->works_pct ?? 0);
        $partsPct = (float) ($profile?->parts_pct ?? 0);

        // Manopere finalizate de utilizator în perioadă.
        // Salariul se calculează pe salary_base (frozen la salvare, izolat de marja internă).
        // Fallback la total pentru rânduri legacy (înainte de introducerea marjei interne).
        $worksRevenue = (float) WorkOrderWork::where('master_id', $userId)
            ->where('status', 'done')
            ->whereBetween('updated_at', [$start, $end])
            ->get()
            ->sum(fn ($w) => (float) ($w->salary_base ?? $w->total));
        $worksPctAmount = round($worksRevenue * $worksPct / 100, 2);

        // Marja pe piesele montate de utilizator (nu există FK direct, aprox via work_order.master_id)
        $partsMargin = (float) WorkOrderPart::where('status', 'installed')
            ->whereBetween('updated_at', [$start, $end])
            ->whereHas('workOrder', fn ($q) => $q->where('master_id', $userId))
            ->get()
            ->sum(fn ($p) => ((float) $p->sell_price - (float) $p->buy_price) * (float) $p->qty);
        $partsPctAmount = round($partsMargin * $partsPct / 100, 2);

        // Bonus / penalizări / avans pe perioadă.
        $adjustments = PayrollAdjustment::where('user_id', $userId)
            ->where('period', $period)
            ->get();
        $bonus = (float) $adjustments->where('type', 'bonus')->sum('amount');
        $fines = (float) $adjustments->where('type', 'fine')->sum('amount');
        $advance = (float) $adjustments->where('type', 'advance')->sum('amount');

        $total = round(
            $base + $worksPctAmount + $partsPctAmount + $bonus - $fines - $advance,
            2
        );

        $attrs = [
            'base' => $base,
            'works_revenue' => $worksRevenue,
            'works_pct_amount' => $worksPctAmount,
            'parts_margin' => $partsMargin,
            'parts_pct_amount' => $partsPctAmount,
            'bonus' => $bonus,
            'fines' => $fines,
            'advance' => $advance,
            'total' => max(0, $total),
        ];

        if (! $persist) {
            return new PayrollRun(['user_id' => $userId, 'period' => $period] + $attrs);
        }

        $run = PayrollRun::updateOrCreate(
            ['user_id' => $userId, 'period' => $period, 'company_id' => app(\App\Tenancy\TenantManager::class)->currentId()],
            $attrs
        );

        return $run;
    }
}
