<?php
session_start();

require(realpath(__DIR__ . '/../../../services/Model.php'));
$obj = new Model();
$db = $obj->getConnection();

$userid = isset($_SESSION['userid']) ? $_SESSION['userid'] : null;

function productModelResponse($success, $status, $extra = [])
{
    echo json_encode(array_merge(['success' => $success, 'status' => $status], $extra));
    exit;
}

function getPurchaseForModel(Model $obj, int $purchaseId)
{
    return $obj->rawSqlSingle("SELECT * FROM purchases WHERE purchase_id = '$purchaseId' AND deleted_at IS NULL");
}

function getPurchaseBatchForModel(Model $obj, array $purchase)
{
    $purchaseId = (int)($purchase['purchase_id'] ?? 0);
    $activeBatch = $obj->rawSqlSingle("
        SELECT batch_id
        FROM product_model
        WHERE purchase_id = '$purchaseId'
          AND batch_id IS NOT NULL
          AND batch_id <> ''
        ORDER BY deleted_at IS NULL DESC, id ASC
        LIMIT 1
    ");

    if (!empty($activeBatch['batch_id'])) {
        return $activeBatch['batch_id'];
    }

    $productId = (int)($purchase['product_id'] ?? 0);
    $supplierId = (int)($purchase['supplier_id'] ?? 0);
    $stockRows = $obj->rawSql("
        SELECT batch_id
        FROM stock
        WHERE product_id = '$productId'
          AND supplier_id = '$supplierId'
          AND deleted_at IS NULL
        ORDER BY stock_id ASC
        LIMIT 2
    ");

    if (count($stockRows) === 1 && !empty($stockRows[0]['batch_id'])) {
        return $stockRows[0]['batch_id'];
    }

    return null;
}

function getPurchaseInventoryStats(Model $obj, int $purchaseId)
{
    $stats = $obj->rawSqlSingle("
        SELECT
            COALESCE(SUM(CASE WHEN deleted_at IS NULL THEN 1 ELSE 0 END), 0) AS active_count,
            COALESCE(SUM(CASE WHEN deleted_at IS NULL AND sold = 0 AND returned = 0 THEN 1 ELSE 0 END), 0) AS available_count
        FROM product_model
        WHERE purchase_id = '$purchaseId'
    ");

    return [
        'active_count' => (int)($stats['active_count'] ?? 0),
        'available_count' => (int)($stats['available_count'] ?? 0),
    ];
}

function syncPurchaseModelInventory(PDO $db, Model $obj, array $purchase, $userid)
{
    $purchaseId = (int)$purchase['purchase_id'];
    $batchId = getPurchaseBatchForModel($obj, $purchase);

    if ($batchId === null || $batchId === '') {
        return ['success' => false, 'status' => 'Purchase batch not found'];
    }

    $stats = getPurchaseInventoryStats($obj, $purchaseId);
    if ($stats['active_count'] <= 0) {
        return ['success' => false, 'status' => 'Purchase must have at least one model'];
    }

    $now = date('Y-m-d H:i:s');

    $purchaseStmt = $db->prepare("
        UPDATE purchases
        SET quantity = ?, updated_by = ?, updated_at = ?
        WHERE purchase_id = ?
    ");
    $purchaseStmt->execute([
        $stats['active_count'],
        $userid,
        $now,
        $purchaseId,
    ]);

    $modelStmt = $db->prepare("
        UPDATE product_model
        SET product_id = ?, batch_id = ?, updated_by = ?, updated_at = ?
        WHERE purchase_id = ?
    ");
    $modelStmt->execute([
        (int)$purchase['product_id'],
        $batchId,
        $userid,
        $now,
        $purchaseId,
    ]);

    $stock = $obj->rawSqlSingle("SELECT * FROM stock WHERE batch_id = '$batchId' AND deleted_at IS NULL ORDER BY stock_id ASC LIMIT 1");
    if ($stock) {
        $stockStmt = $db->prepare("
            UPDATE stock
            SET product_id = ?, supplier_id = ?, current_stock = ?, updated_by = ?, updated_at = ?
            WHERE stock_id = ?
        ");
        $stockStmt->execute([
            (int)$purchase['product_id'],
            (int)$purchase['supplier_id'],
            $stats['available_count'],
            $userid,
            $now,
            (int)$stock['stock_id'],
        ]);
    } else {
        $insertStockStmt = $db->prepare("
            INSERT INTO stock (product_id, current_stock, batch_id, supplier_id, created_by, created_at, deleted_at)
            VALUES (?, ?, ?, ?, ?, ?, ?)
        ");
        $insertStockStmt->execute([
            (int)$purchase['product_id'],
            $stats['available_count'],
            $batchId,
            (int)$purchase['supplier_id'],
            $userid,
            $now,
            null,
        ]);
    }

    return ['success' => true, 'batch_id' => $batchId];
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['modelId']) && !isset($_POST['action'])) {
    $modelId = (int)($_POST['modelId'] ?? 0);
    $modelNo = trim($_POST['modelNo'] ?? '');
    $serialNo = trim($_POST['serialNo'] ?? '');
    $expireDate = trim($_POST['expireDate'] ?? '');

    if ($modelId <= 0 || $modelNo === '' || $serialNo === '' || $expireDate === '') {
        productModelResponse(false, 'Please complete all model fields');
    }

    $model = $obj->rawSqlSingle("SELECT * FROM product_model WHERE id = '$modelId' AND deleted_at IS NULL");
    if (!$model) {
        productModelResponse(false, 'Model not found');
    }

    if ((int)$model['sold'] === 1 || (int)$model['returned'] === 1) {
        productModelResponse(false, 'Sold or returned models cannot be edited');
    }

    try {
        $stmt = $db->prepare("
            UPDATE product_model
            SET model_no = ?, serial_no = ?, expire_date = ?, updated_by = ?, updated_at = ?
            WHERE id = ?
        ");
        $stmt->execute([$modelNo, $serialNo, $expireDate, $userid, date('Y-m-d H:i:s'), $modelId]);
        productModelResponse(true, 'Updated successfully');
    } catch (Throwable $e) {
        productModelResponse(false, 'Failed to update model');
    }
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && !isset($_POST['modelId']) && !isset($_POST['action'])) {
    $purchaseId = (int)($_POST['purchaseId'] ?? 0);
    $modelNo = trim($_POST['modelNo'] ?? '');
    $serialNo = trim($_POST['serialNo'] ?? '');
    $expireDate = trim($_POST['expireDate'] ?? '');

    if ($purchaseId <= 0 || $modelNo === '' || $serialNo === '' || $expireDate === '') {
        productModelResponse(false, 'Please complete all model fields');
    }

    $purchase = getPurchaseForModel($obj, $purchaseId);
    if (!$purchase) {
        productModelResponse(false, 'Purchase not found');
    }

    $batchId = getPurchaseBatchForModel($obj, $purchase);
    if ($batchId === null || $batchId === '') {
        productModelResponse(false, 'Purchase batch not found');
    }

    try {
        $db->beginTransaction();

        $insertStmt = $db->prepare("
            INSERT INTO product_model (purchase_id, product_id, batch_id, model_no, serial_no, expire_date, created_by, created_at, deleted_at)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
        ");
        $insertStmt->execute([
            $purchaseId,
            (int)$purchase['product_id'],
            $batchId,
            $modelNo,
            $serialNo,
            $expireDate,
            $userid,
            date('Y-m-d H:i:s'),
            null,
        ]);
        $insertedId = (int)$db->lastInsertId();

        $sync = syncPurchaseModelInventory($db, $obj, $purchase, $userid);
        if (empty($sync['success'])) {
            throw new RuntimeException($sync['status'] ?? 'Failed to sync purchase');
        }

        $db->commit();
        productModelResponse(true, 'Inserted successfully', ['id' => $insertedId, 'batch_id' => $batchId]);
    } catch (Throwable $e) {
        if ($db->inTransaction()) {
            $db->rollBack();
        }
        productModelResponse(false, $e->getMessage() ?: 'Failed to insert model');
    }
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'delete') {
    $modelId = (int)($_POST['modelId'] ?? 0);
    if ($modelId <= 0) {
        productModelResponse(false, 'Model not found');
    }

    $model = $obj->rawSqlSingle("SELECT * FROM product_model WHERE id = '$modelId' AND deleted_at IS NULL");
    if (!$model) {
        productModelResponse(false, 'Model not found');
    }

    if ((int)$model['sold'] === 1 || (int)$model['returned'] === 1) {
        productModelResponse(false, 'Sold or returned models cannot be deleted');
    }

    $purchase = getPurchaseForModel($obj, (int)$model['purchase_id']);
    if (!$purchase) {
        productModelResponse(false, 'Purchase not found');
    }

    try {
        $db->beginTransaction();

        $deleteStmt = $db->prepare("
            UPDATE product_model
            SET deleted_at = ?, updated_by = ?, updated_at = ?
            WHERE id = ?
        ");
        $deleteStmt->execute([date('Y-m-d H:i:s'), $userid, date('Y-m-d H:i:s'), $modelId]);

        $sync = syncPurchaseModelInventory($db, $obj, $purchase, $userid);
        if (empty($sync['success'])) {
            throw new RuntimeException($sync['status'] ?? 'Failed to sync purchase');
        }

        $db->commit();
        productModelResponse(true, 'Deleted successfully');
    } catch (Throwable $e) {
        if ($db->inTransaction()) {
            $db->rollBack();
        }
        productModelResponse(false, $e->getMessage() ?: 'Failed to delete model');
    }
}
