<?php

namespace App\Http\Controllers;

use App\Models\Account;
use App\Support\BranchContext;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controllers\HasMiddleware;
use Illuminate\Routing\Controllers\Middleware;
use Illuminate\Validation\Rule;
use Illuminate\View\View;

class AccountController extends Controller implements HasMiddleware
{
    public static function middleware(): array
    {
        return [
            new Middleware('can:accounting.view', only: ['index']),
            new Middleware('can:accounting.create', only: ['create', 'store']),
            new Middleware('can:accounting.update', only: ['edit', 'update']),
            new Middleware('can:accounting.delete', only: ['destroy']),
        ];
    }

    public function index(): View
    {
        $accounts = Account::orderBy('code')->get()->groupBy('type');

        return view('accounting.accounts.index', compact('accounts'));
    }

    public function create(): View
    {
        return view('accounting.accounts.create', ['account' => new Account(), 'parents' => $this->parents()]);
    }

    public function store(Request $request, BranchContext $context): RedirectResponse
    {
        $branchId = $context->currentId() ?? auth()->user()->branch_id ?? \App\Models\Branch::min('id');
        $data = $this->validateData($request, $branchId);
        $data['branch_id'] = $branchId;
        Account::create($data);

        return redirect()->route('accounts.index')->with('success', 'Account created.');
    }

    public function edit(Account $account): View
    {
        return view('accounting.accounts.edit', ['account' => $account, 'parents' => $this->parents($account->id)]);
    }

    public function update(Request $request, Account $account): RedirectResponse
    {
        $account->update($this->validateData($request, $account->branch_id, $account->id));

        return redirect()->route('accounts.index')->with('success', 'Account updated.');
    }

    public function destroy(Account $account): RedirectResponse
    {
        if ($account->is_system) {
            return back()->with('error', 'System accounts cannot be deleted.');
        }
        if ($account->lines()->exists()) {
            return back()->with('error', 'Account has transactions and cannot be deleted.');
        }
        $account->delete();

        return redirect()->route('accounts.index')->with('success', 'Account deleted.');
    }

    private function parents(?int $exceptId = null)
    {
        return Account::orderBy('code')->when($exceptId, fn ($q) => $q->where('id', '!=', $exceptId))->get();
    }

    private function validateData(Request $request, int $branchId, ?int $id = null): array
    {
        $data = $request->validate([
            'code' => ['required', 'string', 'max:20', Rule::unique('accounts', 'code')->where('branch_id', $branchId)->ignore($id)],
            'name' => ['required', 'string', 'max:150'],
            'type' => ['required', Rule::in(Account::TYPES)],
            'parent_id' => ['nullable', 'exists:accounts,id'],
            'cash_bank' => ['nullable', Rule::in(['cash', 'bank'])],
            'opening_balance' => ['nullable', 'numeric'],
            'is_active' => ['nullable', 'boolean'],
            'description' => ['nullable', 'string', 'max:255'],
        ]);
        $data['is_active'] = (bool) ($data['is_active'] ?? false);
        $data['opening_balance'] = $data['opening_balance'] ?? 0;

        return $data;
    }
}
