<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\Auth;
use App\Core\Csrf;
use App\Core\DB;
use App\Core\Request;
use App\Core\Response;
use App\Modules\Finance\Application\Services\FinanceRouteContext;
use App\Repositories\CheckRepository;
use App\Services\CheckService;
use Throwable;

final class CheckController
{
    private \PDO $pdo;
    private CheckRepository $repo;
    private CheckService $service;
    private FinanceRouteContext $routeContext;

    public function __construct()
    {
        $this->pdo = DB::pdo();
        $this->repo = new CheckRepository($this->pdo);
        $this->service = new CheckService($this->pdo, $this->repo);
        $this->routeContext = new FinanceRouteContext();
    }

    private function ensureSchema(bool $needsCashboxes = false): bool
    {
        try {
            $this->service->ensureSchemaOrThrow($needsCashboxes);
            return true;
        } catch (Throwable $e) {
            Response::view('pages/dashboard', ['error' => $e->getMessage()]);
            return false;
        }
    }

    private function routeData(): array
    {
        return [
            'checks_url' => $this->routeContext->checksPath(),
            'check_receive_url' => $this->routeContext->checkReceivePath(),
            'check_view_base_url' => $this->routeContext->checkViewPath(),
            'check_endorse_base_url' => $this->routeContext->checkEndorsePath(),
            'check_return_base_url' => $this->routeContext->checkReturnPath(),
            'check_replace_base_url' => $this->routeContext->checkReplacePath(),
            'check_settle_cash_base_url' => $this->routeContext->checkSettleCashPath(),
            'check_alerts_url' => $this->routeContext->checkAlertsPath(),
        ];
    }

    public function index(): void
    {
        Auth::requireLogin();
        require_permission('checks.view');
        if (!$this->ensureSchema()) return;
        $page = max(1, (int) Request::get('page', 1));
        $data = $this->service->list(trim((string)Request::get('q', '')), trim((string)Request::get('status', '')));
        $pagination = paginate_rows($data['rows'] ?? [], $page, 25);
        $data['rows'] = $pagination['items'];
        $data += ['page'=>$pagination['page'],'per_page'=>$pagination['per_page'],'total_pages'=>$pagination['total_pages'],'total_rows'=>$pagination['total_rows'],'from_row'=>$pagination['from'],'to_row'=>$pagination['to']];
        Response::view('pages/checks/index', $data + $this->routeData());
    }

    public function receiveForm(): void
    {
        Auth::requireLogin();
        require_permission('checks.create');
        if (!$this->ensureSchema()) return;
        $data = $this->service->loadReceiveForm();
        if (Request::isPost()) {
            Csrf::verify();
            try {
                $checkId = $this->service->receive(Request::all(), (int)(current_user_id() ?: 0));
                Response::flash('success', 'تم استلام الشيك وتسجيله كأداة سداد على العميل.');
                Response::redirect($this->routeContext->checkViewPath($checkId));
                return;
            } catch (Throwable $e) {
                $data['form'] = array_merge($data['form'], Request::all());
                $data['errors'] = ['حدث خطأ أثناء الحفظ: ' . $e->getMessage()];
            }
        }
        Response::view('pages/checks/receive_form', $data + $this->routeData());
    }

    public function view(): void
    {
        Auth::requireLogin();
        require_permission('checks.view');
        if (!$this->ensureSchema()) return;
        $id = (int)Request::get('id', 0);
        if ($id <= 0) { http_response_code(400); exit('Bad request'); }
        try {
            Response::view('pages/checks/view', $this->service->loadView($id) + $this->routeData());
        } catch (Throwable $e) {
            if ($e->getMessage() === 'Check not found') { http_response_code(404); exit('Check not found'); }
            Response::flash('danger', $e->getMessage());
            Response::redirect($this->routeContext->checksPath());
        }
    }

    public function endorseForm(): void
    {
        Auth::requireLogin();
        require_permission('checks.endorse');
        if (!$this->ensureSchema()) return;
        $id = (int)Request::get('id', 0);
        try {
            $data = $this->service->loadEndorseForm($id);
        } catch (Throwable $e) {
            Response::flash('danger', $e->getMessage());
            Response::redirect($this->routeContext->checkViewPath($id));
            return;
        }
        if (Request::isPost()) {
            Csrf::verify();
            try {
                $this->service->endorse($id, Request::all(), (int)(current_user_id() ?: 0));
                Response::flash('success', 'تم تظهير الشيك للمورد وتخفيض رصيده المستحق.');
                Response::redirect($this->routeContext->checkViewPath($id));
                return;
            } catch (Throwable $e) {
                $data['form'] = array_merge($data['form'], Request::all());
                $data['errors'] = ['حدث خطأ أثناء التظهير: ' . $e->getMessage()];
            }
        }
        Response::view('pages/checks/endorse_form', $data + $this->routeData());
    }

    public function returnForm(): void
    {
        Auth::requireLogin();
        require_permission('checks.return');
        if (!$this->ensureSchema()) return;
        $id = (int)Request::get('id', 0);
        try {
            $data = $this->service->loadReturnForm($id);
        } catch (Throwable $e) {
            Response::flash('danger', $e->getMessage());
            Response::redirect($this->routeContext->checkViewPath($id));
            return;
        }
        if (Request::isPost()) {
            Csrf::verify();
            try {
                $this->service->performReturn($id, Request::all(), (int)(current_user_id() ?: 0));
                Response::flash('success', 'تم تنفيذ رجوع الشيك وتسجيل أثره على الطرف/الأطراف المرتبطة.');
                Response::redirect($this->routeContext->checkViewPath($id));
                return;
            } catch (Throwable $e) {
                $data['form'] = array_merge($data['form'], Request::all());
                $data['errors'] = ['حدث خطأ أثناء تنفيذ الرجوع: ' . $e->getMessage()];
            }
        }
        Response::view('pages/checks/return_form', $data + $this->routeData());
    }

    public function replaceForm(): void
    {
        Auth::requireLogin();
        require_permission('checks.replace');
        if (!$this->ensureSchema()) return;
        $id = (int)Request::get('id', 0);
        try {
            $data = $this->service->loadReplaceForm($id);
        } catch (Throwable $e) {
            Response::flash('danger', $e->getMessage());
            Response::redirect($this->routeContext->checkViewPath($id));
            return;
        }
        if (Request::isPost()) {
            Csrf::verify();
            try {
                $newId = $this->service->replace($id, Request::all(), (int)(current_user_id() ?: 0));
                Response::flash('success', 'تم استبدال الشيك المرتد بشيك جديد وتسجيله كأداة سداد.');
                Response::redirect($this->routeContext->checkViewPath($newId));
                return;
            } catch (Throwable $e) {
                $data['form'] = array_merge($data['form'], Request::all());
                $data['errors'] = ['حدث خطأ أثناء الاستبدال: ' . $e->getMessage()];
            }
        }
        Response::view('pages/checks/replace_form', $data + $this->routeData());
    }

    public function cashSettleForm(): void
    {
        Auth::requireLogin();
        require_permission('checks.settle');
        if (!$this->ensureSchema(true)) return;
        $id = (int)Request::get('id', 0);
        try {
            $data = $this->service->loadCashSettleForm($id);
        } catch (Throwable $e) {
            Response::flash('danger', $e->getMessage());
            Response::redirect($this->routeContext->checkViewPath($id));
            return;
        }
        if (Request::isPost()) {
            Csrf::verify();
            try {
                $this->service->settleCash($id, Request::all(), (int)(current_user_id() ?: 0));
                Response::flash('success', 'تمت تسوية الشيك المرتد نقدًا وإقفال حالته.');
                Response::redirect($this->routeContext->checkViewPath($id));
                return;
            } catch (Throwable $e) {
                $data['form'] = array_merge($data['form'], Request::all());
                $data['errors'] = ['حدث خطأ أثناء التسوية: ' . $e->getMessage()];
            }
        }
        Response::view('pages/checks/cash_settle_form', $data + $this->routeData());
    }
}
