<?php

namespace App\Http\Controllers\Web\Payroll\V2;

use App\Http\Controllers\Controller;
use App\Models\PayrollCycle;
use App\Models\PayrollRunLog;
use App\Services\Payroll\V2\PayrollCycleService;
use App\Services\Payroll\V2\PayrollRunService;
use Illuminate\Http\Request;

class PayrollRunController extends Controller
{
    public function __construct(
        protected PayrollRunService $runService,
        protected PayrollCycleService $cycleService
    ) {}

    public function run(Request $request, PayrollCycle $cycle)
    {
        $companyId = auth()->user()->company_id;
        if ($companyId && (int) $cycle->company_id !== $companyId) {
            abort(403);
        }
        try {
            $this->cycleService->ensureNotLocked($cycle);
        } catch (\RuntimeException $e) {
            return redirect()->route('payroll.v2.cycles.run', $cycle)->with('error', $e->getMessage());
        }
        $result = $this->runService->run($cycle, auth()->id());
        $msg = $result['processed'] . ' employee(s) processed.';
        if ($result['skipped'] > 0) {
            $msg .= ' ' . $result['skipped'] . ' skipped.';
        }
        if (! empty($result['errors'])) {
            $msg .= ' Errors: ' . implode('; ', array_slice($result['errors'], 0, 3));
        }
        return redirect()->route('payroll.v2.cycles.run', $cycle)->with('success', $msg);
    }

    public function complete(Request $request, PayrollCycle $cycle)
    {
        $companyId = auth()->user()->company_id;
        if ($companyId && (int) $cycle->company_id !== $companyId) {
            abort(403);
        }
        try {
            $this->cycleService->transitionToCompleted($cycle, auth()->id());
            PayrollRunLog::withoutGlobalScopes()->create([
                'company_id' => $cycle->company_id,
                'payroll_cycle_id' => $cycle->id,
                'actor_user_id' => auth()->id(),
                'action' => 'completed',
                'payload' => ['at' => now()->toIso8601String()],
            ]);
        } catch (\RuntimeException $e) {
            return redirect()->route('payroll.v2.cycles.run', $cycle)->with('error', $e->getMessage());
        }
        return redirect()->route('payroll.v2.cycles.run', $cycle)->with('success', 'Payroll marked as completed.');
    }

    public function lock(Request $request, PayrollCycle $cycle)
    {
        $companyId = auth()->user()->company_id;
        if ($companyId && (int) $cycle->company_id !== $companyId) {
            abort(403);
        }
        $this->cycleService->lock($cycle, auth()->id());
        PayrollRunLog::withoutGlobalScopes()->create([
            'company_id' => $cycle->company_id,
            'payroll_cycle_id' => $cycle->id,
            'actor_user_id' => auth()->id(),
            'action' => 'locked',
            'payload' => ['at' => now()->toIso8601String()],
        ]);
        return redirect()->route('payroll.v2.cycles.run', $cycle)->with('success', 'Payroll cycle locked.');
    }

    public function unlock(Request $request, PayrollCycle $cycle)
    {
        $companyId = auth()->user()->company_id;
        if ($companyId && (int) $cycle->company_id !== $companyId) {
            abort(403);
        }
        $this->cycleService->unlock($cycle);
        PayrollRunLog::withoutGlobalScopes()->create([
            'company_id' => $cycle->company_id,
            'payroll_cycle_id' => $cycle->id,
            'actor_user_id' => auth()->id(),
            'action' => 'unlocked',
            'payload' => ['at' => now()->toIso8601String()],
        ]);
        return redirect()->route('payroll.v2.cycles.run', $cycle)->with('success', 'Payroll cycle unlocked.');
    }
}
