<?php
class PurchaseController {
    public function index(): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();

        $page = (int)($_GET['page'] ?? 1) ?: 1;
        $search = $_GET['search'] ?? '';

        $purchases = Purchase::listPaginated($page, ['search' => $search]);
        
        $pageTitle = 'Stock Purchases';
        ob_start();
        include APP_ROOT . '/views/tenant/purchases/index.php';
        $content = ob_get_clean();
        include APP_ROOT . '/views/tenant/layouts/main.php';
    }

    public function create(): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();

        $tid = Auth::tenantId();
        $suppliers = Supplier::all();
        $locations = db()->prepare("SELECT * FROM locations WHERE tenant_id=?");
        $locations->execute([$tid]);
        $locations = $locations->fetchAll();

        // Products for searching
        $prods = db()->prepare("SELECT id, name, sku, cost_price, batch_tracking, serial_tracking FROM products WHERE tenant_id=? AND is_active=1");
        $prods->execute([$tid]);
        $products = $prods->fetchAll();

        // Load payment methods settings
        $stmt = db()->prepare("SELECT * FROM settings WHERE tenant_id=?");
        $stmt->execute([$tid]);
        $settingsRaw = $stmt->fetchAll();
        $settings = [];
        foreach ($settingsRaw as $s) { $settings[$s['setting_key']] = $s['setting_value']; }

        $currencySymbol = $settings['currency_symbol'] ?? 'GH₵';

        $pageTitle = 'Add Purchase';
        ob_start();
        include APP_ROOT . '/views/tenant/purchases/create.php';
        $content = ob_get_clean();
        include APP_ROOT . '/views/tenant/layouts/main.php';
    }

    public function store(): void {
        Auth::requireLogin();
        Security::checkCsrf();
        
        $input = json_decode(file_get_contents('php://input'), true);
        if (!$input) { redirectBack(); return; }

        try {
            $locationId = (int)$input['location_id'];
            
            $purchaseData = [
                'supplier_id'     => $input['supplier_id'],
                'status'          => 'received',
                'subtotal'        => (float)($input['subtotal'] ?? 0),
                'tax_amount'      => (float)($input['tax_amount'] ?? 0),
                'discount_amount' => (float)($input['discount_amount'] ?? 0),
                'total'           => (float)$input['total'],
                'amount_paid'     => (float)$input['amount_paid'] ?? 0,
                'payment_method'  => $input['payment_method'] ?? 'cash',
                'payment_status'  => $this->calculatePaymentStatus((float)$input['amount_paid'] ?? 0, (float)$input['total']),
                'note'            => Security::sanitize($input['notes'] ?? '')
            ];
            
            // Process items: map cost_price to unit_cost
            $items = [];
            foreach ($input['items'] as $item) {
                $items[] = [
                    'product_id'  => $item['product_id'],
                    'batch_no'    => $item['batch_no'] ?? null,
                    'expiry_date' => $item['expiry_date'] ?? null,
                    'quantity'    => $item['quantity'],
                    'unit_cost'   => $item['cost_price'],
                    'total'       => $item['total']
                ];
            }

            $purchaseId = Purchase::createWithItems($purchaseData, $items, $locationId);

            header('Content-Type: application/json');
            echo json_encode(['success' => true, 'id' => $purchaseId]);
        } catch (Exception $e) {
            http_response_code(500);
            echo json_encode(['error' => $e->getMessage()]);
        }
    }

    public function show(string $id): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();

        $purchase = Purchase::withItems((int)$id);
        if (!$purchase) { flash('error', 'Purchase not found'); redirect('purchases'); }

        $pageTitle = 'Purchase Detail: ' . e($purchase['purchase_no']);
        ob_start();
        include APP_ROOT . '/views/tenant/purchases/show.php';
        $content = ob_get_clean();
        include APP_ROOT . '/views/tenant/layouts/main.php';
    }

    public function edit(string $id): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();

        $purchase = Purchase::withItems((int)$id);
        if (!$purchase) { flash('error', 'Purchase not found'); redirect('purchases'); }

        $tid = Auth::tenantId();
        $suppliers = Supplier::all();
        $locations = db()->prepare("SELECT * FROM locations WHERE tenant_id=?");
        $locations->execute([$tid]);
        $locations = $locations->fetchAll();

        // Products for searching
        $prods = db()->prepare("SELECT id, name, sku, cost_price, batch_tracking, serial_tracking FROM products WHERE tenant_id=? AND is_active=1");
        $prods->execute([$tid]);
        $products = $prods->fetchAll();

        $pageTitle = 'Edit Purchase: ' . e($purchase['purchase_no']);
        ob_start();
        include APP_ROOT . '/views/tenant/purchases/edit.php';
        $content = ob_get_clean();
        include APP_ROOT . '/views/tenant/layouts/main.php';
    }

    public function update(string $id): void {
        Auth::requireLogin();
        Security::checkCsrf();

        $purchase = Purchase::find((int)$id);
        if (!$purchase) { flash('error', 'Purchase not found'); redirect('purchases'); }

        try {
            db()->beginTransaction();

            $amountPaid = (float)$_POST['amount_paid'];
            $total = (float)$_POST['total'];
            $paymentStatus = $this->calculatePaymentStatus($amountPaid, $total);

            $stmt = db()->prepare(
                "UPDATE purchases SET supplier_id=?, subtotal=?, tax_amount=?, discount_amount=?, total=?, amount_paid=?, payment_method=?, payment_status=?, status=?, note=? WHERE id=?"
            );
            $stmt->execute([
                $_POST['supplier_id'] ?: null,
                (float)$_POST['subtotal'],
                (float)($_POST['tax_amount'] ?? 0),
                (float)($_POST['discount_amount'] ?? 0),
                $total,
                $amountPaid,
                Security::sanitize($_POST['payment_method']),
                $paymentStatus,
                Security::sanitize($_POST['status']),
                Security::sanitize($_POST['notes'] ?? ''),
                $id
            ]);

            db()->commit();
            flash('success', 'Purchase updated successfully');
            redirect('purchases/' . $id);
        } catch (Exception $e) {
            db()->rollBack();
            flash('error', 'Error updating purchase: ' . $e->getMessage());
            redirectBack();
        }
    }

    public function delete(string $id): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();

        $purchase = Purchase::find((int)$id);
        if (!$purchase) { flash('error', 'Purchase not found'); redirect('purchases'); }

        try {
            db()->beginTransaction();

            // Delete purchase items
            $stmt = db()->prepare("DELETE FROM purchase_items WHERE purchase_id = ?");
            $stmt->execute([$id]);

            // Delete purchase
            $stmt = db()->prepare("DELETE FROM purchases WHERE id = ?");
            $stmt->execute([$id]);

            db()->commit();
            flash('success', 'Purchase deleted successfully');
            redirect('purchases');
        } catch (Exception $e) {
            db()->rollBack();
            flash('error', 'Error deleting purchase: ' . $e->getMessage());
            redirect('purchases');
        }
    }

    public function pay(string $id): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();

        $purchase = Purchase::find((int)$id);
        if (!$purchase) { flash('error', 'Purchase not found'); redirect('purchases'); }

        $dueAmount = $purchase['total'] - $purchase['amount_paid'];
        if ($dueAmount <= 0) { flash('error', 'No due payment for this purchase'); redirect('purchases'); }

        $pageTitle = 'Pay Purchase: ' . e($purchase['purchase_no']);
        ob_start();
        include APP_ROOT . '/views/tenant/purchases/pay.php';
        $content = ob_get_clean();
        include APP_ROOT . '/views/tenant/layouts/main.php';
    }

    public function processPaymentFromModal(): void {
        Auth::requireLogin();
        Security::checkCsrf();

        $purchaseId = (int)($_POST['purchase_id'] ?? 0);
        if (!$purchaseId) { flash('error', 'Purchase ID is required'); redirectBack(); }

        $purchase = Purchase::find($purchaseId);
        if (!$purchase) { flash('error', 'Purchase not found'); redirectBack(); }

        $paymentAmount = (float)$_POST['payment_amount'];
        $dueAmount = $purchase['total'] - $purchase['amount_paid'];

        if ($paymentAmount > $dueAmount) {
            flash('error', 'Payment amount cannot exceed due amount');
            redirectBack();
        }

        try {
            db()->beginTransaction();

            $newAmountPaid = $purchase['amount_paid'] + $paymentAmount;
            $newPaymentStatus = $newAmountPaid >= $purchase['total'] ? 'paid' : 'partial';

            $stmt = db()->prepare(
                "UPDATE purchases SET amount_paid = ?, payment_status = ?, payment_method = ? WHERE id = ?"
            );
            $stmt->execute([
                $newAmountPaid,
                $newPaymentStatus,
                Security::sanitize($_POST['payment_method']),
                $purchaseId
            ]);

            // Record payment
            $stmt = db()->prepare(
                "INSERT INTO payments (tenant_id, type, reference_id, amount, method, note, user_id) VALUES (?, ?, ?, ?, ?, ?, ?)"
            );
            $stmt->execute([
                Auth::tenantId(),
                'purchase',
                $purchaseId,
                $paymentAmount,
                Security::sanitize($_POST['payment_method']),
                Security::sanitize($_POST['notes'] ?? ''),
                Auth::userId()
            ]);

            // Record in supplier ledger if supplier exists
            if ($purchase['supplier_id']) {
                SupplierLedger::addEntry([
                    'supplier_id' => $purchase['supplier_id'],
                    'transaction_type' => 'payment',
                    'reference_id' => $purchaseId,
                    'reference_no' => $purchase['purchase_no'],
                    'debit' => 0,
                    'credit' => $paymentAmount,
                    'description' => 'Payment for purchase ' . $purchase['purchase_no'],
                    'transaction_date' => date('Y-m-d')
                ]);
            }

            db()->commit();
            flash('success', 'Payment processed successfully');
            redirect('reports?report=purchase-pay-due');
        } catch (Exception $e) {
            db()->rollBack();
            flash('error', 'Error processing payment: ' . $e->getMessage());
            redirectBack();
        }
    }

    public function processPayment(string $id): void {
        Auth::requireLogin();
        Security::checkCsrf();

        $purchase = Purchase::find((int)$id);
        if (!$purchase) { flash('error', 'Purchase not found'); redirect('purchases'); }

        $paymentAmount = (float)$_POST['payment_amount'];
        $dueAmount = $purchase['total'] - $purchase['amount_paid'];

        if ($paymentAmount > $dueAmount) {
            flash('error', 'Payment amount cannot exceed due amount');
            redirect('purchases/' . $id . '/pay');
        }

        try {
            db()->beginTransaction();

            $newAmountPaid = $purchase['amount_paid'] + $paymentAmount;
            $newPaymentStatus = $newAmountPaid >= $purchase['total'] ? 'paid' : 'partial';

            $stmt = db()->prepare(
                "UPDATE purchases SET amount_paid = ?, payment_status = ?, payment_method = ? WHERE id = ?"
            );
            $stmt->execute([
                $newAmountPaid,
                $newPaymentStatus,
                Security::sanitize($_POST['payment_method']),
                $id
            ]);

            // Record payment
            $stmt = db()->prepare(
                "INSERT INTO payments (tenant_id, type, reference_id, amount, method, note, user_id) VALUES (?, ?, ?, ?, ?, ?, ?)"
            );
            $stmt->execute([
                Auth::tenantId(),
                'purchase',
                $id,
                $paymentAmount,
                Security::sanitize($_POST['payment_method']),
                Security::sanitize($_POST['notes'] ?? ''),
                Auth::userId()
            ]);

            // Record in supplier ledger if supplier exists
            if ($purchase['supplier_id']) {
                SupplierLedger::addEntry([
                    'supplier_id' => $purchase['supplier_id'],
                    'transaction_type' => 'payment',
                    'reference_id' => $id,
                    'reference_no' => $purchase['purchase_no'],
                    'debit' => 0,
                    'credit' => $paymentAmount,
                    'description' => 'Payment for purchase ' . $purchase['purchase_no'],
                    'transaction_date' => date('Y-m-d')
                ]);
            }

            db()->commit();
            flash('success', 'Payment processed successfully');
            redirect('purchases');
        } catch (Exception $e) {
            db()->rollBack();
            flash('error', 'Error processing payment: ' . $e->getMessage());
            redirect('purchases/' . $id . '/pay');
        }
    }

    private function calculatePaymentStatus(float $amountPaid, float $total): string {
        if ($amountPaid >= $total) {
            return 'paid';
        } elseif ($amountPaid > 0) {
            return 'partial';
        } else {
            return 'due';
        }
    }
}
