<?php

namespace App\Livewire\CashSessions;

use App\Domain\Financial\Models\CashSession;
use App\Domain\Financial\Services\CashSessionService;
use App\Domain\Shared\Exceptions\DomainException;
use App\Domain\Shared\Traits\UsesBranchScope;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Layout('layouts.app')]
#[Title('إدارة الوردية')]
class CashSessionManage extends Component
{
    use UsesBranchScope;

    public ?CashSession $currentSession = null;

    // Open form
    public float $opening_balance = 0;
    public string $opening_notes = '';

    // Close form
    public float $closing_balance = 0;
    public string $closing_notes = '';

    public function mount(): void
    {
        $this->authorize('cash_sessions.manage');

        $this->currentSession = CashSession::where('user_id', auth()->id())
            ->where('status', 'open')
            ->first();

        if ($this->currentSession) {
            $expected = ($this->currentSession->opening_balance + $this->currentSession->total_cash_in - $this->currentSession->total_cash_out) / 100;
            $this->closing_balance = $expected;
        }
    }

    public function openSession(CashSessionService $service): void
    {
        $this->validate([
            'opening_balance' => 'required|numeric|min:0',
        ], [
            'opening_balance.required' => 'رصيد الافتتاح مطلوب',
            'opening_balance.min' => 'رصيد الافتتاح يجب ألا يكون سالب',
        ]);

        // A till is opened where the cashier is standing. The branch used to
        // arrive from the form — a plain public property validated with
        // `exists:branches,id`, which accepts every branch in the academy — so a
        // crafted request could open a drawer in another branch and file the
        // whole shift's cash in its books. It now comes from the active branch,
        // and refuses outright when there is no single branch to be in.
        $branchId = $this->getActiveBranchIdOrFail();

        try {
            $amountInPiasters = (int) round($this->opening_balance * 100);
            $this->currentSession = $service->open(auth()->user(), $branchId, $amountInPiasters, $this->opening_notes ?: null);
            $this->opening_balance = 0;
            $this->opening_notes = '';
            session()->flash('success', __('تم فتح الوردية بنجاح'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function closeSession(CashSessionService $service): void
    {
        $this->validate([
            'closing_balance' => 'required|numeric|min:0',
        ], [
            'closing_balance.required' => 'رصيد الإغلاق مطلوب',
            'closing_balance.min' => 'رصيد الإغلاق يجب ألا يكون سالب',
        ]);

        try {
            $amountInPiasters = (int) round($this->closing_balance * 100);
            $service->close($this->currentSession, $amountInPiasters, $this->closing_notes ?: null);
            $this->currentSession = null;
            session()->flash('success', __('تم إغلاق الوردية بنجاح'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function render()
    {
        return view('livewire.cash-sessions.cash-session-manage', [
            // The branch the drawer will belong to — shown, never chosen. Null
            // only in all-branches mode, where opening a till is refused.
            'branch' => $this->branchContext()->currentBranch(),
        ]);
    }
}
