<?php
// ============================================================
//  MediCore — Hold & Resume API
//  Stores draft sales and purchase orders without touching
//  stock, accounting, or any business data.
// ============================================================
require_once '../includes/db.php';
require_once '../includes/auth.php';
require_login();
session_write_close();

header('Content-Type: application/json');

// ── Ensure hold tables exist ──────────────────────────────────
$pdo = db();
$pdo->exec("
CREATE TABLE IF NOT EXISTS sales_hold (
    id            INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    hold_ref      VARCHAR(30)   NOT NULL,
    user_id       INT UNSIGNED  DEFAULT NULL,
    user_name     VARCHAR(100)  DEFAULT '',
    customer_id   INT UNSIGNED  DEFAULT 1,
    customer_name VARCHAR(150)  DEFAULT 'Walk-in',
    sale_mode     VARCHAR(20)   DEFAULT 'retail',
    disc_mode     VARCHAR(10)   DEFAULT 'pct',
    disc_value    DECIMAL(12,2) DEFAULT 0.00,
    paid_amount   DECIMAL(12,2) DEFAULT 0.00,
    pay_type      VARCHAR(20)   DEFAULT 'Cash',
    notes         TEXT,
    items_json    MEDIUMTEXT    NOT NULL,
    total_amount  DECIMAL(12,2) DEFAULT 0.00,
    item_count    INT           DEFAULT 0,
    status        ENUM('hold','resumed','deleted') DEFAULT 'hold',
    is_auto       TINYINT(1)    DEFAULT 0,
    created_at    TIMESTAMP     DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_user   (user_id),
    INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE IF NOT EXISTS purchase_hold (
    id            INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    hold_ref      VARCHAR(30)   NOT NULL,
    user_id       INT UNSIGNED  DEFAULT NULL,
    user_name     VARCHAR(100)  DEFAULT '',
    supplier_id   INT UNSIGNED  DEFAULT NULL,
    supplier_name VARCHAR(150)  DEFAULT '',
    pur_mode      VARCHAR(20)   DEFAULT 'unit_trvat',
    notes         TEXT,
    items_json    MEDIUMTEXT    NOT NULL,
    total_amount  DECIMAL(12,2) DEFAULT 0.00,
    item_count    INT           DEFAULT 0,
    status        ENUM('hold','resumed','deleted') DEFAULT 'hold',
    is_auto       TINYINT(1)    DEFAULT 0,
    created_at    TIMESTAMP     DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_user   (user_id),
    INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
");

// Existing installs from before `is_auto` existed won't have picked it up
// from CREATE TABLE IF NOT EXISTS above (that only applies to brand-new
// tables) — add it defensively, same pattern used throughout this app.
foreach (['sales_hold', 'purchase_hold'] as $__tbl) {
    try {
        $__has = db_val(
            "SELECT COUNT(*) FROM information_schema.COLUMNS
              WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = 'is_auto'",
            [$__tbl]
        );
        if (!$__has) {
            db_run("ALTER TABLE `$__tbl` ADD COLUMN is_auto TINYINT(1) DEFAULT 0 AFTER status");
        }
    } catch (Throwable $e) { /* best-effort */ }
}
unset($__tbl, $__has);

$body   = json_decode(file_get_contents('php://input'), true) ?? [];
$action = trim($body['action'] ?? '');

try {
    match($action) {
        'save_sale'       => api_save_sale($body),
        'list_sales'      => api_list_sales($body),
        'get_sale'        => api_get_sale($body),
        'view_sale'       => api_view_sale($body),
        'save_purchase'   => api_save_purchase($body),
        'list_purchases'  => api_list_purchases($body),
        'get_purchase'    => api_get_purchase($body),
        'view_purchase'   => api_view_purchase($body),
        'delete'          => api_delete($body),
        default           => fail('Unknown action'),
    };
} catch (Throwable $e) {
    fail($e->getMessage());
}

// ── Helpers ───────────────────────────────────────────────────
function next_hold_ref(string $prefix): string {
    $today = date('Ymd');
    $count = db_val(
        "SELECT COUNT(*) FROM " . ($prefix === 'HSL' ? 'sales_hold' : 'purchase_hold') .
        " WHERE DATE(created_at) = CURDATE()"
    ) ?? 0;
    return $prefix . '-' . $today . '-' . str_pad($count + 1, 3, '0', STR_PAD_LEFT);
}

// ── Sales Hold ────────────────────────────────────────────────
function api_save_sale(array $b): void {
    $uid      = current_user_id();
    $uname    = current_user_name();
    $items    = $b['items']     ?? [];
    $total    = (float)($b['total_amount'] ?? 0);
    $ref      = next_hold_ref('HSL');

    // items required — an "auto" save with an empty cart (e.g. fired after
    // a sale already completed and reset the page) isn't a real draft.
    if (!$items) fail('Nothing to hold.');

    $id = db_insert(
        "INSERT INTO sales_hold
           (hold_ref, user_id, user_name, customer_id, customer_name,
            sale_mode, disc_mode, disc_value, paid_amount, pay_type,
            notes, items_json, total_amount, item_count, is_auto)
         VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
        [
            $ref,
            $uid ?: null,
            $uname,
            (int)($b['customer_id']   ?? 1),
            trim($b['customer_name']  ?? 'Walk-in'),
            trim($b['sale_mode']      ?? 'retail'),
            trim($b['disc_mode']      ?? 'pct'),
            (float)($b['disc_value']  ?? 0),
            (float)($b['paid_amount'] ?? 0),
            trim($b['pay_type']       ?? 'Cash'),
            trim($b['notes']          ?? ''),
            json_encode($items),
            $total,
            count($items),
            !empty($b['auto']) ? 1 : 0,
        ]
    );

    ok(['hold_id' => $id, 'hold_ref' => $ref]);
}

function api_list_sales(array $b): void {
    $uid   = current_user_id();
    $q     = trim($b['q'] ?? '');
    $admin = is_admin() || current_user_role() === 'manager';

    $where  = ["status = 'hold'"];
    $params = [];

    if (!$admin) {
        $where[]  = "user_id = ?";
        $params[] = $uid;
    }
    if ($q) {
        $where[]  = "(hold_ref LIKE ? OR customer_name LIKE ? OR user_name LIKE ?)";
        $like     = "%$q%";
        $params   = array_merge($params, [$like, $like, $like]);
    }

    $sql  = "SELECT id, hold_ref, user_name, customer_name, sale_mode,
                    total_amount, item_count, is_auto, created_at
               FROM sales_hold
              WHERE " . implode(' AND ', $where) .
             " ORDER BY created_at DESC LIMIT 50";

    ok(['data' => db_rows($sql, $params)]);
}

// Non-consuming read — unlike api_get_sale(), does NOT mark the hold
// 'resumed'. Lets the Resume list show a "View" preview of a hold's
// items without invalidating it, so accidentally clicking View doesn't
// burn the hold the way Resume does.
function api_view_sale(array $b): void {
    $id    = (int)($b['id'] ?? 0);
    $uid   = current_user_id();
    $admin = is_admin() || current_user_role() === 'manager';

    $row = db_row(
        "SELECT * FROM sales_hold WHERE id = ? AND status = 'hold'",
        [$id]
    );
    if (!$row) fail('Hold not found or already resumed.');
    if (!$admin && (int)$row['user_id'] !== $uid) fail('Access denied.');

    $row['items'] = json_decode($row['items_json'], true) ?? [];
    unset($row['items_json']);
    ok(['data' => $row]);
}

function api_get_sale(array $b): void {
    $id   = (int)($b['id'] ?? 0);
    $uid  = current_user_id();
    $admin= is_admin() || current_user_role() === 'manager';

    $row = db_row(
        "SELECT * FROM sales_hold WHERE id = ? AND status = 'hold'",
        [$id]
    );
    if (!$row) fail('Hold not found or already resumed.');
    if (!$admin && (int)$row['user_id'] !== $uid) fail('Access denied.');

    $row['items'] = json_decode($row['items_json'], true) ?? [];
    unset($row['items_json']);

    // Mark as resumed
    db_run("UPDATE sales_hold SET status = 'resumed' WHERE id = ?", [$id]);
    ok(['data' => $row]);
}

// ── Purchase Hold ─────────────────────────────────────────────
function api_save_purchase(array $b): void {
    $uid   = current_user_id();
    $uname = current_user_name();
    $items = $b['items'] ?? [];
    $total = (float)($b['total_amount'] ?? 0);
    $ref   = next_hold_ref('HPO');

    if (!$items) fail('Nothing to hold.');

    $id = db_insert(
        "INSERT INTO purchase_hold
           (hold_ref, user_id, user_name, supplier_id, supplier_name,
            pur_mode, notes, items_json, total_amount, item_count, is_auto)
         VALUES (?,?,?,?,?,?,?,?,?,?,?)",
        [
            $ref,
            $uid ?: null,
            $uname,
            ($b['supplier_id'] ? (int)$b['supplier_id'] : null),
            trim($b['supplier_name'] ?? ''),
            trim($b['pur_mode']      ?? 'unit_trvat'),
            trim($b['notes']         ?? ''),
            json_encode($items),
            $total,
            count($items),
            !empty($b['auto']) ? 1 : 0,
        ]
    );

    ok(['hold_id' => $id, 'hold_ref' => $ref]);
}

function api_list_purchases(array $b): void {
    $uid   = current_user_id();
    $q     = trim($b['q'] ?? '');
    $admin = is_admin() || current_user_role() === 'manager';

    $where  = ["status = 'hold'"];
    $params = [];

    if (!$admin) {
        $where[]  = "user_id = ?";
        $params[] = $uid;
    }
    if ($q) {
        $where[]  = "(hold_ref LIKE ? OR supplier_name LIKE ? OR user_name LIKE ?)";
        $like     = "%$q%";
        $params   = array_merge($params, [$like, $like, $like]);
    }

    $sql = "SELECT id, hold_ref, user_name, supplier_name, pur_mode,
                   total_amount, item_count, is_auto, created_at
              FROM purchase_hold
             WHERE " . implode(' AND ', $where) .
            " ORDER BY created_at DESC LIMIT 50";

    ok(['data' => db_rows($sql, $params)]);
}

// Non-consuming read — see api_view_sale() for why this exists separately
// from api_get_purchase().
function api_view_purchase(array $b): void {
    $id    = (int)($b['id'] ?? 0);
    $uid   = current_user_id();
    $admin = is_admin() || current_user_role() === 'manager';

    $row = db_row(
        "SELECT * FROM purchase_hold WHERE id = ? AND status = 'hold'",
        [$id]
    );
    if (!$row) fail('Hold not found or already resumed.');
    if (!$admin && (int)$row['user_id'] !== $uid) fail('Access denied.');

    $row['items'] = json_decode($row['items_json'], true) ?? [];
    unset($row['items_json']);
    ok(['data' => $row]);
}

function api_get_purchase(array $b): void {
    $id    = (int)($b['id'] ?? 0);
    $uid   = current_user_id();
    $admin = is_admin() || current_user_role() === 'manager';

    $row = db_row(
        "SELECT * FROM purchase_hold WHERE id = ? AND status = 'hold'",
        [$id]
    );
    if (!$row) fail('Hold not found or already resumed.');
    if (!$admin && (int)$row['user_id'] !== $uid) fail('Access denied.');

    $row['items'] = json_decode($row['items_json'], true) ?? [];
    unset($row['items_json']);

    db_run("UPDATE purchase_hold SET status = 'resumed' WHERE id = ?", [$id]);
    ok(['data' => $row]);
}

// ── Delete any hold ───────────────────────────────────────────
function api_delete(array $b): void {
    $id   = (int)($b['id']   ?? 0);
    $type = trim($b['type']  ?? 'sale');  // 'sale' | 'purchase'
    $uid  = current_user_id();
    $admin= is_admin() || current_user_role() === 'manager';

    $tbl = $type === 'purchase' ? 'purchase_hold' : 'sales_hold';
    $row = db_row("SELECT user_id FROM $tbl WHERE id = ?", [$id]);
    if (!$row) fail('Hold not found.');
    if (!$admin && (int)$row['user_id'] !== $uid) fail('Access denied — only managers can delete holds by others.');

    db_run("UPDATE $tbl SET status = 'deleted' WHERE id = ?", [$id]);
    ok(['msg' => 'Hold deleted.']);
}

// ── Response helpers ──────────────────────────────────────────
function ok(array $extra = []): void {
    echo json_encode(array_merge(['success' => true], $extra)); exit;
}
function fail(string $msg): never {
    echo json_encode(['success' => false, 'error' => $msg]); exit;
}
