<?php

namespace App\Http\Controllers;

use App\Models\Branch;
use App\Models\OperationalExpense;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class OperationalExpenseController extends Controller
{
    private const MANUAL_TYPES = [
        'operational' => 'Operasional',
        'delivery' => 'Ongkir / Delivery',
        'supplies' => 'Perlengkapan',
        'maintenance' => 'Maintenance',
        'rent' => 'Sewa',
        'salary' => 'Gaji / Upah',
        'marketing' => 'Marketing',
        'other' => 'Lainnya',
    ];

    public function index(Request $request)
    {
        $user = $request->user();
        $branches = Branch::query()
            ->when(! $user->isOwner(), fn ($query) => $query->whereKey($user->branch_id))
            ->orderBy('name')
            ->get();

        $filters = $request->validate([
            'branch_id' => ['nullable', 'integer', 'exists:branches,id'],
            'start' => ['nullable', 'date'],
            'end' => ['nullable', 'date', 'after_or_equal:start'],
            'type' => ['nullable', 'string'],
        ]);

        $branchId = $user->isOwner()
            ? ($filters['branch_id'] ?? null)
            : $user->branch_id;

        if ($branchId) {
            abort_unless($user->canAccessBranch((int) $branchId), 403);
        }

        $start = $filters['start'] ?? now()->startOfMonth()->toDateString();
        $end = $filters['end'] ?? now()->toDateString();
        $type = $filters['type'] ?? null;

        $expenseQuery = OperationalExpense::query()
            ->with(['branch', 'user'])
            ->when($branchId, fn ($query) => $query->where('branch_id', $branchId))
            ->when(! $branchId && ! $user->isOwner(), fn ($query) => $query->where('branch_id', $user->branch_id))
            ->whereBetween('expense_date', [$start, $end])
            ->when($type, fn ($query) => $query->where('type', $type));

        $total = (clone $expenseQuery)->sum('amount');

        $expenses = $expenseQuery
            ->latest('expense_date')
            ->latest('id')
            ->paginate(15)
            ->withQueryString();

        return view('expenses.index', [
            'branches' => $branches,
            'expenses' => $expenses,
            'filters' => ['branch_id' => $branchId, 'start' => $start, 'end' => $end, 'type' => $type],
            'types' => self::MANUAL_TYPES,
            'typeLabels' => self::MANUAL_TYPES + ['bonus_payout' => 'Pencairan Bonus'],
            'total' => $total,
        ]);
    }

    public function store(Request $request)
    {
        $data = $this->validatedData($request);
        $user = $request->user();

        abort_unless($user->canAccessBranch((int) $data['branch_id']), 403);

        DB::transaction(function () use ($data, $user): void {
            OperationalExpense::query()->create($data + ['user_id' => $user->id]);
        });

        return back()->with('status', 'Biaya berhasil ditambahkan.');
    }

    public function update(Request $request, OperationalExpense $expense)
    {
        abort_if($expense->type === 'bonus_payout', 403, 'Biaya pencairan bonus tidak bisa diedit dari input biaya manual.');
        abort_unless($request->user()->canAccessBranch((int) $expense->branch_id), 403);

        $data = $this->validatedData($request);
        abort_unless($request->user()->canAccessBranch((int) $data['branch_id']), 403);

        DB::transaction(fn () => $expense->update($data));

        return back()->with('status', 'Biaya berhasil diperbarui.');
    }

    public function destroy(Request $request, OperationalExpense $expense)
    {
        abort_if($expense->type === 'bonus_payout', 403, 'Biaya pencairan bonus tidak bisa dihapus dari input biaya manual.');
        abort_unless($request->user()->canAccessBranch((int) $expense->branch_id), 403);

        DB::transaction(fn () => $expense->delete());

        return back()->with('status', 'Biaya berhasil dihapus.');
    }

    private function validatedData(Request $request): array
    {
        return $request->validate([
            'branch_id' => ['required', 'integer', 'exists:branches,id'],
            'expense_date' => ['required', 'date'],
            'name' => ['required', 'string', 'max:255'],
            'amount' => ['required', 'numeric', 'min:0.01', 'max:999999999999.99'],
            'type' => ['required', 'string', 'in:'.implode(',', array_keys(self::MANUAL_TYPES))],
            'description' => ['nullable', 'string', 'max:1000'],
        ]);
    }
}
