<?php

namespace Tests\Feature\Audit;

use App\Models\Central\Company;
use App\Models\Central\Plan;
use App\Models\Tenant\Client;
use App\Models\Tenant\EmployeeProfile;
use App\Models\Tenant\PayrollAdjustment;
use App\Models\Tenant\User;
use App\Models\Tenant\Vehicle;
use App\Models\Tenant\WorkOrder;
use App\Models\Tenant\WorkOrderPart;
use App\Models\Tenant\WorkOrderWork;
use App\Services\PayrollCalculator;
use App\Tenancy\TenantManager;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon;
use Tests\TestCase;

class PayrollCalculatorTest extends TestCase
{
    use RefreshDatabase;

    public function test_compute_combines_base_works_parts_and_adjustments(): void
    {
        Carbon::setTestNow('2026-06-15');
        $ctx = $this->bootTenant();
        $user = $this->makeMaster();
        EmployeeProfile::create([
            'user_id' => $user->id,
            'base_salary' => 5000,
            'works_pct' => 30,   // 30% from done work revenue
            'parts_pct' => 10,   // 10% from parts margin
        ]);

        $client = Client::create(['name' => 'C', 'phone' => '+37399100100', 'type' => 'individual', 'status' => 'active']);
        $vehicle = Vehicle::create(['client_id' => $client->id, 'make' => 'X', 'model' => 'Y', 'plate' => 'PR-1']);
        $wo = WorkOrder::create([
            'number' => WorkOrder::generateNumber($ctx['company']->id),
            'client_id' => $client->id, 'vehicle_id' => $vehicle->id,
            'opened_at' => today()->subDays(3), 'status' => 'in_work',
            'master_id' => $user->id,
        ]);

        // A done labor: 2h × 400 = 800 → 30% = 240
        WorkOrderWork::create([
            'work_order_id' => $wo->id, 'master_id' => $user->id,
            'name' => 'X', 'hours' => 2, 'price_per_hour' => 400, 'status' => 'done',
        ]);

        // An installed part: sell 350 - buy 200 = 150 margin × 1 qty → 10% = 15
        WorkOrderPart::create([
            'work_order_id' => $wo->id,
            'name' => 'P', 'qty' => 1, 'sell_price' => 350, 'buy_price' => 200,
            'status' => 'installed',
        ]);

        // Adjustments for the period
        PayrollAdjustment::create([
            'user_id' => $user->id, 'period' => '2026-06',
            'type' => 'bonus', 'amount' => 500, 'date' => today(),
        ]);
        PayrollAdjustment::create([
            'user_id' => $user->id, 'period' => '2026-06',
            'type' => 'fine', 'amount' => 100, 'date' => today(),
        ]);
        PayrollAdjustment::create([
            'user_id' => $user->id, 'period' => '2026-06',
            'type' => 'advance', 'amount' => 200, 'date' => today(),
        ]);

        $run = app(PayrollCalculator::class)->compute($user->id, '2026-06');

        // base 5000 + works 240 + parts 15 + bonus 500 - fine 100 - advance 200 = 5455
        $this->assertEquals(5455.0, (float) $run->total);
        $this->assertEquals(5000.0, (float) $run->base);
        $this->assertEquals(240.0, (float) $run->works_pct_amount);
        $this->assertEquals(15.0, (float) $run->parts_pct_amount);

        Carbon::setTestNow();
    }

    public function test_compute_ignores_other_periods_and_other_users(): void
    {
        Carbon::setTestNow('2026-06-15');
        $ctx = $this->bootTenant();
        $me = $this->makeMaster();
        $other = $this->makeMaster();
        EmployeeProfile::create(['user_id' => $me->id, 'base_salary' => 1000, 'works_pct' => 100, 'parts_pct' => 0]);

        $c = Client::create(['name' => 'X', 'phone' => '+37300000000', 'type' => 'individual', 'status' => 'active']);
        $v = Vehicle::create(['client_id' => $c->id, 'make' => 'X', 'model' => 'Y', 'plate' => 'NOISE']);
        $wo = WorkOrder::create([
            'number' => WorkOrder::generateNumber($ctx['company']->id),
            'client_id' => $c->id, 'vehicle_id' => $v->id,
            'opened_at' => today(), 'status' => 'in_work',
        ]);

        // Another master's work — must be excluded.
        WorkOrderWork::create([
            'work_order_id' => $wo->id, 'master_id' => $other->id,
            'name' => 'X', 'hours' => 5, 'price_per_hour' => 400, 'status' => 'done',
        ]);
        // Adjustment for a different period — must be excluded.
        PayrollAdjustment::create([
            'user_id' => $me->id, 'period' => '2026-05',
            'type' => 'bonus', 'amount' => 9999, 'date' => today()->subMonth(),
        ]);

        $run = app(PayrollCalculator::class)->compute($me->id, '2026-06');
        $this->assertEquals(1000.0, (float) $run->total, 'only base — no own works, no current-period adjustments');
        Carbon::setTestNow();
    }

    private function bootTenant(): array
    {
        $plan = Plan::firstOrCreate(['slug' => 'test'], ['name' => 'T', 'price' => 0, 'features' => []]);
        $company = Company::create([
            'plan_id' => $plan->id, 'slug' => 'pr-' . uniqid(),
            'name' => 'Payroll Co', 'status' => 'active',
        ]);
        app(TenantManager::class)->setCurrent($company);
        return compact('company');
    }

    private function makeMaster(): User
    {
        return User::create([
            'name' => 'M', 'email' => 'm-' . uniqid() . '@example.com',
            'password' => bcrypt('x'), 'role' => 'master', 'status' => 'active',
        ]);
    }
}
