<?php

namespace Modules\Accounting\Controllers;

use App\Controllers\BaseController;
use App\Models\BankAccountModel;
use App\Models\BankReconciliationLineModel;
use App\Models\BankReconciliationModel;
use Modules\Accounting\Services\BankReconciliationService;

class BankReconciliationController extends BaseController
{
    protected BankReconciliationModel $recons;
    protected BankReconciliationLineModel $lines;
    protected BankReconciliationService $service;
    protected BankAccountModel $banks;

    public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
    {
        parent::initController($request, $response, $logger);
        $this->recons  = new BankReconciliationModel();
        $this->lines   = new BankReconciliationLineModel();
        $this->service = new BankReconciliationService();
        $this->banks   = new BankAccountModel();
    }

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

        $reconciliations = $this->recons
            ->scopeForList($search ?: null, $status, $bankAccountId ? (int) $bankAccountId : null)
            ->orderBy('bank_reconciliations.statement_date', 'DESC')
            ->orderBy('bank_reconciliations.id', 'DESC')
            ->findAll();

        return view('Modules\Accounting\Views\bank_reconciliations\index', array_merge($this->baseViewData(), [
            'title'           => 'Bank Reconciliations',
            'reconciliations' => $reconciliations,
            'bankAccounts'    => $this->banks->getActive(),
            'filters'         => compact('search', 'status', 'bankAccountId'),
        ]));
    }

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

    public function store()
    {
        if (! $this->validate([
            'bank_account_id'          => 'required|is_natural_no_zero',
            'statement_date'           => 'required|valid_date',
            'statement_ending_balance' => '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/bank-reconciliations/' . $result['id'])->with('success', 'Reconciliation created.');
    }

    public function show(int $id)
    {
        $recon = $this->recons->scopeForList()->where('bank_reconciliations.id', $id)->first();
        if (! $recon) {
            return redirect()->to('/accounting/bank-reconciliations')->with('error', 'Reconciliation not found.');
        }

        $lines = $this->lines->getForReconciliation($id);

        return view('Modules\Accounting\Views\bank_reconciliations\show', array_merge($this->baseViewData(), [
            'title' => 'Reconciliation ' . $recon['number'],
            'recon' => $recon,
            'lines' => $lines,
        ]));
    }

    public function editForm(int $id)
    {
        $recon = $this->recons->scopeForList()->where('bank_reconciliations.id', $id)->first();
        if (! $recon) {
            return redirect()->to('/accounting/bank-reconciliations')->with('error', 'Reconciliation not found.');
        }
        if ($recon['status'] !== 'draft') {
            return redirect()->to('/accounting/bank-reconciliations/' . $id)->with('error', 'Only draft reconciliations can be edited.');
        }

        $lines = $this->lines->getForReconciliation($id);

        return view('Modules\Accounting\Views\bank_reconciliations\edit', array_merge($this->baseViewData(), [
            'title'        => 'Edit Reconciliation',
            'recon'        => $recon,
            'lines'        => $lines,
            'bankAccounts' => $this->banks->getActive(),
        ]));
    }

    public function update(int $id)
    {
        if (! $this->validate([
            'statement_date'           => 'required|valid_date',
            'statement_ending_balance' => 'required|decimal',
        ])) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $input = $this->request->getPost();
        if ($this->request->getPost('lines_submitted') !== null) {
            $input['lines'] = $this->request->getPost('lines') ?? [];
        }

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

        return redirect()->to('/accounting/bank-reconciliations/' . $id)->with('success', 'Reconciliation updated.');
    }

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

        return redirect()->to('/accounting/bank-reconciliations/' . $id)->with('success', 'Reconciliation completed.');
    }

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

        return redirect()->to('/accounting/bank-reconciliations')->with('success', 'Reconciliation deleted.');
    }
}
