<?php

declare(strict_types=1);

namespace App\Modules\Inventory\Application\Services;

use PDO;

final class WarehouseDocsPageService
{
    public function handleIndex(): void
    {
        require_login();
        require_permission('stock.vouchers.view');

        $pdo = db();
        $this->renderIndex($this->loadIndexData($pdo, $_GET));
    }

    public function handleView(): void
    {
        require_login();
        require_permission('stock.vouchers.view');

        $pdo = db();
        $id = (int) ($_GET['id'] ?? 0);
        if ($id <= 0) {
            http_response_code(400);
            die('Invalid document id');
        }

        $this->renderView($this->loadDocument($pdo, $id));
    }

    public function handlePrint(): void
    {
        (new \App\Modules\Inventory\Presentation\Controllers\WarehouseDocPrintController($this))();
    }

    public function pageData(): array
    {
        return [
            'dashboard' => WarehouseDocsRouteContext::dashboard(),
            'inventory_home' => WarehouseDocsRouteContext::inventoryHome(),
            'index' => WarehouseDocsRouteContext::index(),
            'view' => static fn(int $id): string => WarehouseDocsRouteContext::view($id),
            'print' => static fn(int $id, string $format = ''): string => WarehouseDocsRouteContext::print($id, $format),
        ];
    }

    public function loadIndexData(PDO $pdo, array $query): array
    {
        $from = (string)($query['from'] ?? date('Y-m-01'));
        $to = (string)($query['to'] ?? date('Y-m-d'));
        $type = (string)($query['type'] ?? '');
        $status = (string)($query['status'] ?? '');
        $warehouseId = (int)($query['warehouse_id'] ?? 0);
        $search = trim((string)($query['q'] ?? ''));

        $warehouses = get_warehouses($pdo);

        $where = ["d.doc_date >= ?", "d.doc_date < ?"];
        $params = [$from . " 00:00:00", date("Y-m-d 00:00:00", strtotime($to . " +1 day"))];

        if ($type !== '') {
            $where[] = "d.doc_type = ?";
            $params[] = $type;
        }
        if ($status !== '') {
            $where[] = "d.status = ?";
            $params[] = $status;
        }
        if ($warehouseId > 0) {
            $where[] = "d.warehouse_id = ?";
            $params[] = $warehouseId;
        }
        if ($search !== '') {
            $where[] = "(d.doc_no LIKE ? OR d.notes LIKE ?)";
            $params[] = '%' . $search . '%';
            $params[] = '%' . $search . '%';
        }

        $sql = "
          SELECT d.*, w.name AS warehouse_name, tw.name AS to_warehouse_name,
                 COALESCE(u.full_name, u.username) AS created_by_name,
                 (SELECT COUNT(*) FROM wh_doc_lines l WHERE l.doc_id=d.id) AS lines_count
          FROM wh_docs d
          JOIN warehouses w ON w.id=d.warehouse_id
          LEFT JOIN warehouses tw ON tw.id=d.to_warehouse_id
          LEFT JOIN users u ON u.id=d.created_by
          WHERE " . implode(' AND ', $where) . "
          ORDER BY d.id DESC
          LIMIT 300
        ";

        $st = $pdo->prepare($sql);
        $st->execute($params);
        $allDocs = $st->fetchAll() ?: [];
        $page = max(1, (int)($query['page'] ?? 1));
        $pagination = paginate_rows($allDocs, $page, 25);

        return [
            'docs' => $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'],
            'warehouses' => $warehouses,
            'from' => $from,
            'to' => $to,
            'type' => $type,
            'status' => $status,
            'warehouse_id' => $warehouseId,
            'q' => $search,
        ];
    }

    public function renderIndex(array $data): void
    {
        $routeContext = $this->pageData();
        view('pages/stock/wh_docs_list', array_merge($data, [
            'routeContext' => $routeContext,
            'page_title' => 'استعلام أذونات المخازن',
            'breadcrumbs' => [
                ['label' => 'لوحة التحكم', 'url' => $routeContext['dashboard']],
                ['label' => 'المخزون', 'url' => $routeContext['inventory_home']],
                ['label' => 'استعلام أذونات المخازن'],
            ],
        ]));
    }

    public function loadDocument(PDO $pdo, int $id): array
    {
        $st = $pdo->prepare("\n  SELECT d.*, w.name AS warehouse_name, tw.name AS to_warehouse_name\n  FROM wh_docs d\n  JOIN warehouses w ON w.id=d.warehouse_id\n  LEFT JOIN warehouses tw ON tw.id=d.to_warehouse_id\n  WHERE d.id=?\n");
        $st->execute([$id]);
        $doc = $st->fetch();

        if (!$doc) {
            http_response_code(404);
            die('Document not found');
        }

        $st2 = $pdo->prepare("\n  SELECT l.*, i.name AS item_name, u.name AS unit_name, u.symbol AS unit_symbol\n  FROM wh_doc_lines l\n  JOIN items i ON i.id=l.item_id\n  LEFT JOIN units u ON u.id=l.unit_id\n  WHERE l.doc_id=?\n  ORDER BY l.line_no, l.id\n");
        $st2->execute([$id]);
        $lines = $st2->fetchAll() ?: [];

        return ['doc' => $doc, 'lines' => $lines];
    }

    public function renderView(array $data): void
    {
        $routeContext = $this->pageData();
        $doc = $data['doc'];
        view('pages/stock/wh_doc_view', [
            'doc' => $doc,
            'lines' => $data['lines'],
            'routeContext' => $routeContext,
            'page_title' => 'عرض إذن مخزن',
            'breadcrumbs' => [
                ['label' => 'لوحة التحكم', 'url' => $routeContext['dashboard']],
                ['label' => 'المخزون', 'url' => $routeContext['inventory_home']],
                ['label' => 'استعلام أذونات المخازن', 'url' => $routeContext['index']],
                ['label' => (string)($doc['doc_no'] ?? ('#' . (int)($doc['id'] ?? 0)))],
            ],
        ]);
    }



    public function buildPrintPayload(PDO $pdo, int $id): array
    {
        $data = $this->loadPrintData($pdo, $id);
        $doc = $data['doc'];
        $lines = $data['lines'];

        $typeLabel = doc_type_label((string)($doc['doc_type'] ?? ''));
        $title = 'إذن مخزن - ' . $typeLabel;

        $createdBy = trim((string)($doc['full_name'] ?? ''));
        if ($createdBy === '') {
            $createdBy = (string)($doc['username'] ?? '-');
        }

        $meta = [
            'no' => (string)($doc['doc_no'] ?? ''),
            'date' => (string)substr((string)($doc['doc_date'] ?? ''), 0, 10),
            'status' => (string)($doc['status'] ?? ''),
        ];

        return [
            'title' => $title,
            'meta' => $meta,
            'company' => company_profile($pdo),
            'footer' => [],
            'payload' => [
                'doc' => $doc,
                'lines' => $lines,
                'fromWh' => (string)($doc['warehouse_name'] ?? '-'),
                'toWh' => (string)($doc['to_warehouse_name'] ?? '-'),
                'createdBy' => $createdBy,
                'notes' => (string)($doc['notes'] ?? '-'),
            ],
        ];
    }
    public function loadPrintData(PDO $pdo, int $id): array
    {
        $st = $pdo->prepare("\n  SELECT d.*, w.name AS warehouse_name, tw.name AS to_warehouse_name,\n         u.full_name, u.username\n  FROM wh_docs d\n  JOIN warehouses w ON w.id = d.warehouse_id\n  LEFT JOIN warehouses tw ON tw.id = d.to_warehouse_id\n  LEFT JOIN users u ON u.id = d.created_by\n  WHERE d.id = ?\n");
        $st->execute([$id]);
        $doc = $st->fetch();
        if (!$doc) {
            http_response_code(404);
            die('Document not found');
        }

        $st2 = $pdo->prepare("\n  SELECT l.*, i.name AS item_name,\n         u.name AS unit_name, u.symbol AS unit_symbol\n  FROM wh_doc_lines l\n  JOIN items i ON i.id = l.item_id\n  LEFT JOIN units u ON u.id = l.unit_id\n  WHERE l.doc_id = ?\n  ORDER BY l.line_no, l.id\n");
        $st2->execute([$id]);
        $lines = $st2->fetchAll() ?: [];

        return ['doc' => $doc, 'lines' => $lines];
    }
}
