<?php

namespace App\Http\Controllers\Company\Admin;

use App\Http\Controllers\Controller;
use App\Models\Budget;
use App\Services\BudgetService;
use Illuminate\Http\Request;

class BudgetsController extends Controller
{
    public function __construct(
        private readonly BudgetService $budgets,
    ) {
    }

    private function companyId(): int
    {
        return auth()->user()->company_id;
    }

    private function gate(string $action = 'view'): void
    {
        if (!auth()->user()->hasPermission('budget', $action)) {
            abort(403);
        }
    }

    public function index()
    {
        $this->gate('view');

        return view('company.budgets.index', [
            'budgets' => $this->budgets->list($this->companyId()),
            'canCreate' => auth()->user()->hasPermission('budget', 'create'),
        ]);
    }

    public function create()
    {
        $this->gate('create');

        $options = $this->budgets->formOptions($this->companyId());
        $periodBounds = $this->resolvePeriodBounds(null, $options['currentFiscalYear']);

        return view('company.budgets.form', [
            'budget' => null,
            'lineAmounts' => [],
            'periodMonths' => $this->budgets->periodMonths($periodBounds['from'], $periodBounds['to']),
            ...$periodBounds,
            ...$options,
        ]);
    }

    public function store(Request $request)
    {
        $this->gate('create');

        $validated = $request->validate([
            'name' => 'required|string|max:150',
            'period_from' => 'required|date',
            'period_to' => 'required|date|after_or_equal:period_from',
            'scope_type' => 'required|in:account,dimension,job',
            'dimension_value_id' => 'nullable|integer',
            'customer_id' => 'nullable|integer',
            'notes' => 'nullable|string|max:5000',
            'lines' => 'nullable|array',
        ]);

        $budget = $this->budgets->store($this->companyId(), $validated);

        return redirect()
            ->route('admin.budgets.edit', $budget)
            ->with('success', 'Budget saved.');
    }

    public function edit(Budget $budget)
    {
        $this->gate('view');
        $companyId = $this->companyId();
        $budget->load(['fiscalYear', 'customer', 'dim1Value', 'dim2Value', 'dim3Value']);

        if ($budget->company_id !== $companyId) {
            abort(403);
        }

        $options = $this->budgets->formOptions($companyId);
        $selectedDimensionValueId = $budget->dim1_id ?: $budget->dim2_id ?: $budget->dim3_id;
        $periodBounds = $this->resolvePeriodBounds($budget, $options['currentFiscalYear']);

        return view('company.budgets.form', [
            'budget' => $budget,
            'lineAmounts' => $this->budgets->lineAmountsForBudget($budget),
            'selectedDimensionValueId' => $selectedDimensionValueId,
            'canEdit' => auth()->user()->hasPermission('budget', 'edit'),
            'periodMonths' => $this->budgets->periodMonths($periodBounds['from'], $periodBounds['to']),
            ...$periodBounds,
            ...$options,
        ]);
    }

    public function update(Request $request, Budget $budget)
    {
        $this->gate('edit');

        $validated = $request->validate([
            'name' => 'required|string|max:150',
            'period_from' => 'required|date',
            'period_to' => 'required|date|after_or_equal:period_from',
            'scope_type' => 'required|in:account,dimension,job',
            'dimension_value_id' => 'nullable|integer',
            'customer_id' => 'nullable|integer',
            'notes' => 'nullable|string|max:5000',
            'lines' => 'nullable|array',
        ]);

        $this->budgets->update($this->companyId(), $budget, $validated);

        return redirect()
            ->route('admin.budgets.edit', $budget)
            ->with('success', 'Budget updated.');
    }

    public function destroy(Budget $budget)
    {
        $this->gate('edit');
        $this->budgets->destroy($this->companyId(), $budget);

        return redirect()
            ->route('admin.budgets.index')
            ->with('success', 'Budget deleted.');
    }

    /** @return array{periodFrom: ?string, periodTo: ?string, from: string, to: string} */
    private function resolvePeriodBounds(?Budget $budget, $currentFiscalYear): array
    {
        $periodFrom = old('period_from', $budget?->start_date?->format('Y-m-d') ?? $currentFiscalYear?->start_date?->format('Y-m-d') ?? '');
        $periodTo = old('period_to', $budget?->end_date?->format('Y-m-d') ?? $currentFiscalYear?->end_date?->format('Y-m-d') ?? '');

        return [
            'periodFrom' => $periodFrom,
            'periodTo' => $periodTo,
            'from' => $periodFrom,
            'to' => $periodTo,
        ];
    }
}
