<?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\Repositories\SupplierPaymentRepository;
use App\Services\SupplierPaymentService;
use Throwable;
use App\Modules\Purchases\Application\Services\PurchasesRouteContext;

final class SupplierPaymentController
{
    private \PDO $pdo;
    private SupplierPaymentRepository $repo;
    private SupplierPaymentService $service;
    private PurchasesRouteContext $routeContext;

    public function __construct()
    {
        $this->pdo = DB::pdo();
        $this->repo = new SupplierPaymentRepository($this->pdo);
        $this->service = new SupplierPaymentService($this->pdo, $this->repo);
        $this->routeContext = new PurchasesRouteContext();
    }

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

    public function index(): void
    {
        Auth::requireLogin();
        require_permission('supplier_payments.view');
        if (!$this->ensureSchemaView()) return;
        $q = trim((string)Request::get('q', ''));
        $status = trim((string)Request::get('status', ''));
        $from = trim((string)Request::get('from', ''));
        $to = trim((string)Request::get('to', ''));
        $page = max(1, (int) Request::get('page', 1));
        $pagination = paginate_rows($this->repo->search($q, $status, $from, $to), $page, 25);
        Response::view('pages/purchases/supplier_payments_index', [
            'supplier_payments_url' => $this->routeContext->supplierPaymentsPath(),
            'supplier_payment_form_url' => $this->routeContext->supplierPaymentFormPath(),
            'supplier_payment_view_base_url' => $this->routeContext->supplierPaymentViewPath(),
            'rows' => $pagination['items'],
            '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'],
            'q' => $q,
            'status' => $status,
            'from' => $from,
            'to' => $to,
        ]);
    }

    public function form(): void
    {
        Auth::requireLogin();
        if (!$this->ensureSchemaView(false, true)) return;
        $id = (int)Request::get('id', 0);
        require_permission($id > 0 ? 'supplier_payments.edit' : 'supplier_payments.create');
        try {
            if (Request::isPost()) {
                Csrf::verify();
                $savedId = $this->service->save($id, Request::all(), (int)(current_user_id() ?: 0));
                Response::flash('success', ((string)Request::post('save_action', 'draft') === 'post') ? 'تم حفظ وترحيل السداد.' : 'تم حفظ السداد كمسودة.');
                Response::redirect($this->routeContext->supplierPaymentViewPath($savedId));
                return;
            }
            $data = $this->service->loadForm($id);
            if (!$id) {
                $prefPartyId = (int)Request::get('party_id', Request::get('supplier_id', 0));
                if ($prefPartyId > 0) {
                    $data['payment']['party_id'] = $prefPartyId;
                    $data['party'] = $this->repo->fetchParty($prefPartyId) ?: null;
                }
            }
            Response::view('pages/purchases/supplier_payment_form', $data + [
                'supplier_payments_url' => $this->routeContext->supplierPaymentsPath(),
                'supplier_payment_view_url' => $this->routeContext->supplierPaymentViewPath($id),
            ]);
        } catch (Throwable $e) {
            $msg = $e->getMessage();
            if ($msg === 'Not found') { http_response_code(404); exit('Not found'); }
            Response::flash('danger', str_contains($msg, 'لا يمكن تعديل سند مُرحّل') ? $msg : ('حدث خطأ أثناء الحفظ: ' . $msg));
            Response::redirect($this->routeContext->supplierPaymentFormPath($id));
        }
    }

    public function view(): void
    {
        Auth::requireLogin();
        require_permission('supplier_payments.view');
        if (!$this->ensureSchemaView(false, true)) return;
        $id = (int)Request::get('id', 0);
        if ($id <= 0) { http_response_code(400); exit('Invalid'); }

        if (Request::isPost() && (string)Request::post('action', '') === 'post') {
            Csrf::verify();
            require_permission('supplier_payments.post');
            try {
                $this->service->postExisting($id, (int)(current_user_id() ?: 0));
                Response::flash('success', 'تم ترحيل السداد.');
            } catch (Throwable $e) {
                Response::flash('danger', 'حدث خطأ أثناء الترحيل: ' . $e->getMessage());
            }
            Response::redirect($this->routeContext->supplierPaymentViewPath($id));
            return;
        }

        try {
            Response::view('pages/purchases/supplier_payment_view', $this->service->loadView($id) + [
                'supplier_payments_url' => $this->routeContext->supplierPaymentsPath(),
                'supplier_payment_form_url' => $this->routeContext->supplierPaymentFormPath(),
            ]);
        } catch (Throwable $e) {
            if ($e->getMessage() === 'Not found') { http_response_code(404); exit('Not found'); }
            Response::flash('danger', $e->getMessage());
            Response::redirect($this->routeContext->supplierPaymentsPath());
        }
    }

    public function statement(): void
    {
        Auth::requireLogin();
        require_permission('suppliers.statement.view');
        if (!$this->ensureSchemaView(false, true)) return;
        $partyId = (int)Request::get('party_id', Request::get('supplier_id', Request::get('customer_id', 0)));
        $from = trim((string)Request::get('from', ''));
        $to = trim((string)Request::get('to', ''));
        $data = $this->service->loadSupplierStatement($partyId, $from, $to);
        Response::view('pages/parties/party_statement', [
            'party_id' => $data['partyId'],
            'party' => $data['party'],
            'from' => $data['from'],
            'to' => $data['to'],
            'opening' => $data['opening'],
            'closing' => $data['closing'],
            'rows' => $data['rows'],
            'page_title' => 'كشف حساب المورد',
            'role' => 'supplier',
            'breadcrumbs' => [
                $this->routeContext->dashboardCrumb(),
                ['label'=>'المشتريات','url'=>$this->routeContext->purchasesBoardPath()],
                ['label'=>'كشف حساب المورد'],
            ],
        ]);
    }

    public function aging(): void
    {
        Auth::requireLogin();
        require_permission('suppliers.aging.view');
        if (!$this->ensureSchemaView(true, false)) return;
        if (!table_exists($this->pdo, 'purchase_invoices')) {
            Response::view('pages/dashboard', ['error' => 'مطلوب تشغيل ملف التحديث: sql/migrate_v1_23_purchases.sql']);
            return;
        }
        $partyId = (int)Request::get('party_id', 0);
        $asOf = trim((string)Request::get('as_of', ''));
        $data = $this->service->loadSupplierAging($partyId, $asOf);
        Response::view('pages/purchases/supplier_aging_report', [
            'as_of' => $data['asOf'],
            'party_id' => $data['partyId'],
            'selected_supplier' => $data['selectedSupplier'],
            'buckets' => $data['buckets'],
            'rows' => $data['rows'],
            'totals' => $data['totals'],
        ]);
    }
}
