<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Cashbox;
use App\Models\CashboxEntry;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class CashboxController extends Controller
{
    public function index()
    {
        $cashboxes = Cashbox::withCount('entries')->get();

        return view('admin.cashboxes.index', compact('cashboxes'));
    }

    public function create()
    {
        return view('admin.cashboxes.create');
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'name' => ['required', 'string', 'max:120'],
            'starting_balance' => ['required', 'numeric', 'min:0'],
            'notes' => ['nullable', 'string'],
        ]);

        $data['current_balance'] = $data['starting_balance'];

        Cashbox::create($data);

        return redirect()->route('admin.cashboxes.index')->with('status', __('app.cashboxes.created'));
    }

    public function show(Cashbox $cashbox)
    {
        $cashbox->load(['entries' => fn ($query) => $query->latest()->limit(50)]);

        return view('admin.cashboxes.show', compact('cashbox'));
    }

    public function edit(Cashbox $cashbox)
    {
        return view('admin.cashboxes.edit', compact('cashbox'));
    }

    public function update(Request $request, Cashbox $cashbox)
    {
        $data = $request->validate([
            'name' => ['required', 'string', 'max:120'],
            'notes' => ['nullable', 'string'],
        ]);

        $cashbox->update($data);

        return redirect()->route('admin.cashboxes.show', $cashbox)->with('status', __('app.cashboxes.updated'));
    }

    public function destroy(Cashbox $cashbox)
    {
        if ($cashbox->entries()->exists()) {
            return redirect()->back()->withErrors(__('app.cashboxes.cannot_delete_with_entries'));
        }

        $cashbox->delete();

        return redirect()->route('admin.cashboxes.index')->with('status', __('app.cashboxes.deleted'));
    }

    public function destroyEntry(Cashbox $cashbox, CashboxEntry $entry)
    {
        // Check permission
        if (!auth()->user()->hasPermission('manage_transactions')) {
            abort(403, 'Unauthorized action.');
        }

        // Verify entry belongs to cashbox
        if ($entry->cashbox_id !== $cashbox->id) {
            abort(404);
        }

        DB::transaction(function () use ($cashbox, $entry) {
            // Reverse the entry amount
            $reverseDirection = $entry->direction === 'in' ? 'out' : 'in';
            $reverseAmount = $entry->amount;

            if ($reverseDirection === 'in') {
                $cashbox->current_balance = $cashbox->current_balance + $reverseAmount;
            } else {
                $cashbox->current_balance = $cashbox->current_balance - $reverseAmount;
            }

            $cashbox->save();

            // Delete the transaction if it exists and has no reference
            // Note: We don't delete transactions with reference_type to maintain data integrity
            // but we still allow deleting the entry itself
            if ($entry->transaction && !$entry->transaction->reference_type) {
                $entry->transaction->delete();
            }

            // Delete the entry
            $entry->delete();

            // Recalculate running balances for all entries after this one
            $this->recalculateBalances($cashbox, $entry->created_at);
        });

        return redirect()->route('admin.cashboxes.show', $cashbox)->with('status', __('app.cashboxes.show.entry_deleted'));
    }

    protected function recalculateBalances(Cashbox $cashbox, $afterDate)
    {
        $entries = $cashbox->entries()
            ->where('created_at', '>', $afterDate)
            ->orderBy('created_at')
            ->get();

        $currentBalance = $cashbox->entries()
            ->where('created_at', '<=', $afterDate)
            ->orderByDesc('created_at')
            ->first()
            ?->running_balance ?? $cashbox->starting_balance;

        foreach ($entries as $entry) {
            if ($entry->direction === 'in') {
                $currentBalance = $currentBalance + $entry->amount;
            } else {
                $currentBalance = $currentBalance - $entry->amount;
            }

            $entry->update(['running_balance' => $currentBalance]);
        }

        $cashbox->current_balance = $currentBalance;
        $cashbox->save();
    }
}

