<?php

namespace Modules\Accounting\Controllers;

use App\Controllers\BaseController;
use App\Models\BankAccountModel;
use App\Models\CashAccountModel;
use App\Models\ChequeModel;
use Modules\Accounting\Services\ChequeService;

class ChequeController extends BaseController
{
    protected ChequeModel $cheques;
    protected ChequeService $service;
    protected BankAccountModel $banks;
    protected CashAccountModel $cash;

    public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
    {
        parent::initController($request, $response, $logger);
        $this->cheques = new ChequeModel();
        $this->service = new ChequeService();
        $this->banks   = new BankAccountModel();
        $this->cash    = new CashAccountModel();
    }

    public function index()
    {
        $search    = trim((string) $this->request->getGet('q'));
        $status    = $this->request->getGet('status') ?: null;
        $direction = $this->request->getGet('direction') ?: null;

        $cheques = $this->cheques
            ->scopeForList($search ?: null, $status, $direction)
            ->orderBy('cheques.cheque_date', 'DESC')
            ->orderBy('cheques.id', 'DESC')
            ->findAll();

        return view('Modules\Accounting\Views\cheques\index', array_merge($this->baseViewData(), [
            'title'   => 'Cheques',
            'cheques' => $cheques,
            'filters' => compact('search', 'status', 'direction'),
        ]));
    }

    public function createForm()
    {
        return view('Modules\Accounting\Views\cheques\create', array_merge($this->baseViewData(), [
            'title'        => 'New Cheque',
            'bankAccounts' => $this->banks->getActive(),
            'cashAccounts' => $this->cash->getActive(),
        ]));
    }

    public function store()
    {
        if (! $this->validate([
            'cheque_number' => 'required|max_length[60]',
            'direction'     => 'required|in_list[issued,received]',
            'party_name'    => 'required|max_length[200]',
            'cheque_date'   => 'required|valid_date',
            'amount'        => 'required|decimal',
        ])) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $result = $this->service->create($this->request->getPost(), (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->back()->withInput()->with('errors', $result['errors']);
        }

        return redirect()->to('/accounting/cheques')->with('success', 'Cheque created.');
    }

    public function show(int $id)
    {
        $cheque = $this->cheques->scopeForList()->where('cheques.id', $id)->first();
        if (! $cheque) {
            return redirect()->to('/accounting/cheques')->with('error', 'Cheque not found.');
        }

        return view('Modules\Accounting\Views\cheques\show', array_merge($this->baseViewData(), [
            'title'  => 'Cheque ' . $cheque['number'],
            'cheque' => $cheque,
        ]));
    }

    public function editForm(int $id)
    {
        $cheque = $this->cheques->find($id);
        if (! $cheque) {
            return redirect()->to('/accounting/cheques')->with('error', 'Cheque not found.');
        }
        if (! in_array($cheque['status'], ['registered', 'issued'], true)) {
            return redirect()->to('/accounting/cheques/' . $id)->with('error', 'Only registered or issued cheques can be edited.');
        }

        return view('Modules\Accounting\Views\cheques\edit', array_merge($this->baseViewData(), [
            'title'        => 'Edit Cheque',
            'cheque'       => $cheque,
            'bankAccounts' => $this->banks->getActive(),
            'cashAccounts' => $this->cash->getActive(),
        ]));
    }

    public function update(int $id)
    {
        if (! $this->validate([
            'cheque_number' => 'required|max_length[60]',
            'direction'     => 'required|in_list[issued,received]',
            'party_name'    => 'required|max_length[200]',
            'cheque_date'   => 'required|valid_date',
            'amount'        => 'required|decimal',
        ])) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $result = $this->service->update($id, $this->request->getPost(), (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->back()->withInput()->with('errors', $result['errors']);
        }

        return redirect()->to('/accounting/cheques/' . $id)->with('success', 'Cheque updated.');
    }

    public function clear(int $id)
    {
        $result = $this->service->clear($id, (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->back()->with('error', $result['error']);
        }

        return redirect()->to('/accounting/cheques/' . $id)->with('success', 'Cheque cleared and journal posted.');
    }

    public function bounce(int $id)
    {
        $result = $this->service->bounce($id, (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->back()->with('error', $result['error']);
        }

        return redirect()->back()->with('success', 'Cheque marked as bounced.');
    }

    public function cancel(int $id)
    {
        $result = $this->service->cancel($id, (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->back()->with('error', $result['error']);
        }

        return redirect()->back()->with('success', 'Cheque cancelled.');
    }

    public function destroy(int $id)
    {
        $result = $this->service->delete($id, (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->to('/accounting/cheques')->with('error', $result['error']);
        }

        return redirect()->to('/accounting/cheques')->with('success', 'Cheque deleted.');
    }
}
