<?php
session_start();

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

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

$limit = isset($_GET['length']) ? intval($_GET['length']) : 10;
$start = isset($_GET['start']) ? intval($_GET['start']) : 0;
$search = $_GET['search']['value'] ?? '';
$wherecond = '';
if (!empty($search)) {
    $wherecond .= " AND (p.product_name LIKE '%$search%' OR  ag.ag_name LIKE '%$search%' OR  ag.ag_mobile_no LIKE '%$search%' )";
}

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

function normalizeSaleModelIds($modelIds)
{
    if (!is_array($modelIds)) {
        return [];
    }

    $normalized = [];
    foreach ($modelIds as $modelId) {
        $modelId = (int)$modelId;
        if ($modelId > 0) {
            $normalized[$modelId] = $modelId;
        }
    }

    return array_values($normalized);
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && !isset($_POST['id'])) {
    $product = (int)($_POST['product'] ?? 0);
    $quantity = (int)($_POST['quantity'] ?? 0);
    $customer = (int)($_POST['customer'] ?? 0);
    $sale_date = trim($_POST['sale_date'] ?? '');
    $batch_id = trim($_POST['batch_id'] ?? '');
    $stock_id = (int)($_POST['stock_id'] ?? 0);
    $model_products = normalizeSaleModelIds($_POST['model_products'] ?? []);

    if ($product <= 0 || $customer <= 0 || $stock_id <= 0 || $quantity <= 0 || $sale_date === '' || $batch_id === '') {
        salesResponse(false, 'Please fill all required sale fields');
    }

    if (count($model_products) !== $quantity) {
        salesResponse(false, 'Selected model count must match quantity');
    }

    $stock_check = $obj->rawSqlSingle("
        SELECT *
        FROM `stock`
        WHERE `stock_id` = '$stock_id'
          AND `product_id` = '$product'
          AND `batch_id` = '$batch_id'
          AND `deleted_at` IS NULL
    ");

    if (!$stock_check) {
        salesResponse(false, 'Stock not found for the selected batch');
    }

    if ((int)$stock_check['current_stock'] < $quantity) {
        salesResponse(false, 'Not enough stock available');
    }

    $modelIdList = implode(',', $model_products);
    $availableModels = $obj->rawSql("
        SELECT id
        FROM product_model
        WHERE id IN ($modelIdList)
          AND product_id = '$product'
          AND batch_id = '$batch_id'
          AND sold = 0
          AND returned = 0
          AND deleted_at IS NULL
    ");

    if (count($availableModels) !== count($model_products)) {
        salesResponse(false, 'One or more selected models are unavailable');
    }

    $model_products_json = json_encode($model_products);
    $stmt = $obj->insertData('sales', [
        'product_id' => $product,
        'model_id' => $model_products_json,
        'batch_id' => $batch_id,
        'quantity' => $quantity,
        'customer_id' => $customer,
        'stock_id' => $stock_id,
        'sale_date' => $sale_date,
        'created_by' => $userid,
        'created_at' => date('Y-m-d H:i:s'),
        'deleted_at' => null
    ]);

    if (!$stmt) {
        salesResponse(false, 'Failed to add sale');
    }

    foreach ($model_products as $model_id) {
        $update_model = $obj->updateData('product_model', ['sold' => 1, 'updated_by' => $userid], ['id' => $model_id]);
        if (!$update_model) {
            salesResponse(false, 'Failed to reserve selected models');
        }
    }

    $update_stock = $obj->updateData(
        'stock',
        [
            'current_stock' => ((int)$stock_check['current_stock']) - $quantity,
            'updated_at' => date('Y-m-d H:i:s'),
            'updated_by' => $userid
        ],
        ['stock_id' => $stock_id]
    );

    if (!$update_stock) {
        salesResponse(false, 'Failed to update stock');
    }

    salesResponse(true, 'Added successfully');
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['id']) && !isset($_POST['action'])) {
    $id = (int)($_POST['id'] ?? 0);
    $batch_id = trim($_POST['batch_id'] ?? '');
    $product = (int)($_POST['product'] ?? 0);
    $quantity = (int)($_POST['quantity'] ?? 0);
    $customer = (int)($_POST['customer'] ?? 0);
    $sale_date = trim($_POST['sale_date'] ?? '');
    $stock_id = (int)($_POST['stock_id'] ?? 0);
    $models = normalizeSaleModelIds($_POST['models'] ?? []);

    if ($id <= 0 || $product <= 0 || $customer <= 0 || $stock_id <= 0 || $quantity <= 0 || $sale_date === '' || $batch_id === '') {
        salesResponse(false, 'Please fill all required sale fields');
    }

    if (count($models) !== $quantity) {
        salesResponse(false, 'Selected model count must match quantity');
    }

    $oldSale = $obj->rawSqlSingle("SELECT * FROM `sales` WHERE `sale_id` = '$id' AND `deleted_at` IS NULL");
    if (!$oldSale) {
        salesResponse(false, 'Sale not found');
    }

    $oldModelIds = normalizeSaleModelIds(json_decode($oldSale['model_id'], true));
    $sortedOldModelIds = $oldModelIds;
    $sortedNewModelIds = $models;
    sort($sortedOldModelIds);
    sort($sortedNewModelIds);

    $hasChanges =
        (int)$oldSale['product_id'] !== $product ||
        (int)$oldSale['stock_id'] !== $stock_id ||
        (int)$oldSale['quantity'] !== $quantity ||
        (int)$oldSale['customer_id'] !== $customer ||
        (string)$oldSale['sale_date'] !== $sale_date ||
        (string)$oldSale['batch_id'] !== $batch_id ||
        $sortedOldModelIds !== $sortedNewModelIds;

    if (!$hasChanges) {
        salesResponse(true, 'No changes found');
    }

    $stock_check = $obj->rawSqlSingle("
        SELECT *
        FROM `stock`
        WHERE `stock_id` = '$stock_id'
          AND `product_id` = '$product'
          AND `batch_id` = '$batch_id'
          AND `deleted_at` IS NULL
    ");

    if (!$stock_check) {
        salesResponse(false, 'Stock not found for the selected batch');
    }

    $availableStock = (int)$stock_check['current_stock'];
    if ((int)$oldSale['stock_id'] === $stock_id) {
        $availableStock += (int)$oldSale['quantity'];
    }

    if ($availableStock < $quantity) {
        salesResponse(false, 'Not enough stock available');
    }

    $existingRequestedModels = array_values(array_intersect($models, $oldModelIds));
    if (!empty($existingRequestedModels)) {
        $existingIdList = implode(',', $existingRequestedModels);
        $currentSaleModels = $obj->rawSql("
            SELECT id
            FROM product_model
            WHERE id IN ($existingIdList)
              AND product_id = '$product'
              AND batch_id = '$batch_id'
              AND deleted_at IS NULL
        ");

        if (count($currentSaleModels) !== count($existingRequestedModels)) {
            salesResponse(false, 'Selected models do not belong to this batch');
        }
    }

    $newRequestedModels = array_values(array_diff($models, $oldModelIds));
    if (!empty($newRequestedModels)) {
        $newIdList = implode(',', $newRequestedModels);
        $availableModels = $obj->rawSql("
            SELECT id
            FROM product_model
            WHERE id IN ($newIdList)
              AND product_id = '$product'
              AND batch_id = '$batch_id'
              AND sold = 0
              AND returned = 0
              AND deleted_at IS NULL
        ");

        if (count($availableModels) !== count($newRequestedModels)) {
            salesResponse(false, 'One or more selected models are unavailable');
        }
    }

    $model_products_json = json_encode($models);
    $updateSale = $obj->updateData(
        'sales',
        [
            'product_id' => $product,
            'quantity' => $quantity,
            'batch_id' => $batch_id,
            'model_id' => $model_products_json,
            'stock_id' => $stock_id,
            'customer_id' => $customer,
            'sale_date' => $sale_date,
            'updated_by' => $userid,
            'updated_at' => date('Y-m-d H:i:s')
        ],
        ['sale_id' => $id]
    );

    if (!$updateSale) {
        salesResponse(false, 'Failed to update sale');
    }

    foreach ($oldModelIds as $modelId) {
        $updateModel = $obj->updateData('product_model', ['sold' => 0, 'updated_by' => $userid], ['id' => $modelId]);
        if (!$updateModel) {
            salesResponse(false, 'Failed to release previous models');
        }
    }

    foreach ($models as $modelId) {
        $updateModel = $obj->updateData('product_model', ['sold' => 1, 'updated_by' => $userid], ['id' => $modelId]);
        if (!$updateModel) {
            salesResponse(false, 'Failed to reserve selected models');
        }
    }

    $oldStock = $obj->rawSqlSingle("SELECT * FROM `stock` WHERE `stock_id` = '" . (int)$oldSale['stock_id'] . "' AND `deleted_at` IS NULL");
    if ($oldStock) {
        $restoreOldStock = $obj->updateData(
            'stock',
            [
                'current_stock' => ((int)$oldStock['current_stock']) + (int)$oldSale['quantity'],
                'updated_at' => date('Y-m-d H:i:s'),
                'updated_by' => $userid
            ],
            ['stock_id' => (int)$oldSale['stock_id']]
        );

        if (!$restoreOldStock) {
            salesResponse(false, 'Failed to restore previous stock');
        }
    }

    $latestStock = $obj->rawSqlSingle("SELECT * FROM `stock` WHERE `stock_id` = '$stock_id' AND `deleted_at` IS NULL");
    if (!$latestStock) {
        salesResponse(false, 'Updated stock not found');
    }

    $deductNewStock = $obj->updateData(
        'stock',
        [
            'current_stock' => ((int)$latestStock['current_stock']) - $quantity,
            'updated_at' => date('Y-m-d H:i:s'),
            'updated_by' => $userid
        ],
        ['stock_id' => $stock_id]
    );

    if (!$deductNewStock) {
        salesResponse(false, 'Failed to update stock');
    }

    salesResponse(true, 'Updated successfully');
}

// if ($_SERVER['REQUEST_METHOD'] === 'GET' && !isset($_GET['sale'])) {
//     $sales = $obj->raw_sql(
//         "
//         SELECT sales.*,
//         p.product_name,
//         ag.ag_name,
//         _createuser.FullName
//         FROM sales
//         LEFT JOIN products p ON sales.product_id = p.product_id
//         LEFT JOIN _createuser ON sales.created_by = _createuser.UserId
//         LEFT JOIN tbl_agent ag ON sales.customer_id = ag.ag_id
//         WHERE sales.quantity > 0 $wherecond order by sales.sale_id desc LIMIT $limit OFFSET $start;
//         "
//     );
//     $totalRecords = $obj->raw_sql("SELECT COUNT(*) FROM sales WHERE deleted_at IS NULL");
//     $totalFiltered = $obj->raw_sql("SELECT COUNT(*) FROM sales WHERE deleted_at IS NULL AND quantity > 0 LIMIT $limit OFFSET $start");

//     $i = 1; // Initialize counter
//     foreach ($sales as &$row) {
//         $row['sl'] = $i++; // Add the row number
//         $model_ids = json_decode($row['model_id'], true);  // Decode as an array

//         if (!is_array($model_ids)) {
//             $model_ids = [];  // Ensure it's an array (in case of decoding errors or wrong format)
//         }

//         $model_numbers = [];  // Initialize an array to store model numbers
//         foreach ($model_ids as $key => $model_id) {
//             // Ensure the model_id is numeric or valid
//             $model = $obj->rawSqlSingle("SELECT * FROM product_model WHERE id = $model_id");

//             // If the model is found, store all relevant data in an associative array
//             if ($model) {
//                 $model_numbers[$key] = [
//                     'model_no'    => $model['model_no'],
//                     'serial_no'   => $model['serial_no'],
//                     'expire_date' => $model['expire_date']
//                 ];
//             }
//         }

//         // Now assign the model_numbers array back to 'model_id' (or another key if needed)
//         $row['model_id'] = $model_numbers;  // This will be an array of associative arrays
//     }

//     // Total records without filtering
//     $totalDataQuery = "
//         SELECT COUNT(*) AS total 
//         FROM sales 
//         WHERE deleted_at IS NULL
//     ";
//     $totalData = $obj->rawSql($totalDataQuery)[0]['total'];

//     // Total records after filtering
//     $totalFilteredQuery = "
//         SELECT COUNT(*) AS total 
//         FROM sales 
//         WHERE deleted_at IS NULL AND quantity > 0 LIMIT $limit OFFSET $start
//     ";
//     $totalFilteredResult = $obj->rawSql($totalFilteredQuery);
//     $totalFiltered = $totalFilteredResult[0]['total'] ?? 0;
//     echo json_encode(
//         [
//             'draw' => isset($_GET['draw']) ? intval($_GET['draw']) : 1,
//             'recordsTotal' => $totalData,
//             'recordsFiltered' => $totalFiltered,
//             'data' => $sales
//         ]
//     );
//     exit;
// } 
else if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['sale'])) {
    $saleId = $_GET['sale'];

    // Fetch sale details
    $sale = $obj->rawSqlSingle("SELECT * FROM `sales` WHERE `sale_id` = '$saleId' AND `deleted_at` IS NULL");

    if ($sale) {
        $modelId = $sale['model_id'];
        $modelIdJson = json_decode($modelId, true);
        if (!is_array($modelIdJson)) {
            $modelIdJson = [];
        }
        $model_numbers = [];

        foreach ($modelIdJson as $key => $modelId) {

            // Query for model details
            $models = $obj->rawSql("SELECT * FROM `product_model` WHERE `id` = '$modelId' AND `sold` = 1 AND `deleted_at` IS NULL");

            if ($models) {
                // Assuming $models is an array and we want to fetch the first result
                $model_numbers[$key] = [
                    'id'          => $models[0]['id'],
                    'model_no'    => $models[0]['model_no'],
                    'serial_no'   => $models[0]['serial_no'],
                    'expire_date' => $models[0]['expire_date']
                ];
            }
        }

        // Return JSON response with model numbers
        echo json_encode(['success' => true, 'models' => $model_numbers]);
    } else {
        // Handle case where the sale is not found
        echo json_encode(['success' => false, 'message' => 'Sale not found']);
    }

    exit;
}
