<?php
// =============================================
// SHARK CRM - Database Connection
// =============================================

define('DB_HOST', 'localhost');
define('DB_USER', 'amctagme_user');
define('DB_PASS', 'tag.amc.2013');
define('DB_NAME', 'amctagme_shark_crm');

// App configuration
require_once __DIR__ . '/config/app.php';

// Upload configuration
define('UPLOAD_DIR', __DIR__ . '/uploads/');
define('UPLOAD_URL', './uploads/');

$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);

if ($conn->connect_error) {
    die(json_encode(['success' => false, 'message' => 'Database connection failed: ' . $conn->connect_error]));
}

$conn->set_charset('utf8mb4');

// Create uploads directory if not exists
if (!is_dir(UPLOAD_DIR)) {
    mkdir(UPLOAD_DIR, 0755, true);
}

function sanitize($conn, $data) {
    return $conn->real_escape_string(trim($data));
}


// ---- Public ID masking helpers ----
// Shows encrypted tokens in URLs/HTML instead of raw database IDs.
// This improves URL privacy, but real security still depends on account_id checks and permissions.
if (!function_exists('crmBase64UrlEncode')) {
    function crmBase64UrlEncode($data) { return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); }
    function crmBase64UrlDecode($data) {
        $data = strtr((string)$data, '-_', '+/');
        $pad = strlen($data) % 4;
        if ($pad) $data .= str_repeat('=', 4 - $pad);
        return base64_decode($data, true);
    }
    function crmIdSecret() {
        $seed = (defined('DB_NAME') ? DB_NAME : '') . '|' . (defined('DB_USER') ? DB_USER : '') . '|' . (defined('DB_PASS') ? DB_PASS : '') . '|sharkcrm-id-v1';
        return hash('sha256', $seed, true);
    }
    function crmEncodeId($id) {
        $id = (int)$id;
        if ($id <= 0) return '';
        if (!function_exists('openssl_encrypt')) {
            $payload = $id . '|' . substr(hash_hmac('sha256', (string)$id, crmIdSecret()), 0, 12);
            return 'm' . crmBase64UrlEncode($payload);
        }
        $iv = random_bytes(16);
        $plain = json_encode(['id'=>$id, 't'=>time()]);
        $cipher = openssl_encrypt($plain, 'AES-256-CBC', crmIdSecret(), OPENSSL_RAW_DATA, $iv);
        return 'm' . crmBase64UrlEncode($iv . $cipher);
    }
    function crmDecodeId($token) {
        if (is_int($token)) return $token;
        $token = trim((string)$token);
        if ($token === '') return 0;
        // Backward compatibility: old numeric URLs/forms still work, but new UI will not print them.
        if (ctype_digit($token)) return (int)$token;
        if ($token[0] === 'm') $token = substr($token, 1);
        $raw = crmBase64UrlDecode($token);
        if ($raw === false || strlen($raw) < 8) return 0;
        if (function_exists('openssl_decrypt') && strlen($raw) > 16) {
            $iv = substr($raw, 0, 16);
            $cipher = substr($raw, 16);
            $plain = openssl_decrypt($cipher, 'AES-256-CBC', crmIdSecret(), OPENSSL_RAW_DATA, $iv);
            $data = json_decode($plain ?: '', true);
            return isset($data['id']) ? (int)$data['id'] : 0;
        }
        $parts = explode('|', $raw);
        if (count($parts) === 2) {
            $id = (int)$parts[0];
            $sig = substr(hash_hmac('sha256', (string)$id, crmIdSecret()), 0, 12);
            return hash_equals($sig, $parts[1]) ? $id : 0;
        }
        return 0;
    }
    function crmEid($id) { return htmlspecialchars(crmEncodeId($id), ENT_QUOTES, 'UTF-8'); }
    function crmId($value) { return crmDecodeId($value); }
    function crmDecodeIdsInArray(&$arr) {
        if (!is_array($arr)) return;
        foreach ($arr as $k => &$v) {
            if (is_array($v)) {
                if (preg_match('/(^ids$|_ids$|Ids$)/', (string)$k)) {
                    foreach ($v as &$oneId) {
                        $decoded = crmDecodeId($oneId);
                        if ($decoded > 0) $oneId = $decoded;
                    }
                } else {
                    crmDecodeIdsInArray($v);
                }
                continue;
            }
            if (preg_match('/(^id$|_id$|Id$)/', (string)$k)) {
                $decoded = crmDecodeId($v);
                if ($decoded > 0) $v = $decoded;
            }
        }
    }
}


if (!function_exists('redirect')) {
    function redirect($url) {
        if (!$url) { $url = 'index.php'; }
        header('Location: ' . $url);
        exit;
    }
}
if (!function_exists('flash')) {
    function flash($type, $message) {
        if (session_status() !== PHP_SESSION_ACTIVE) { @session_start(); }
        $_SESSION['flash'][] = ['type'=>$type, 'message'=>$message];
    }
}

function jsonResponse($success, $message = '', $data = []) {
    header('Content-Type: application/json');
    echo json_encode(array_merge(['success' => $success, 'message' => $message], $data));
    exit;
}

function formatDate($dt) {
    if (!$dt) return 'N/A';
    return date('M d, Y', strtotime($dt));
}

function formatDateTime($dt) {
    if (!$dt) return 'N/A';
    return date('M d, Y H:i', strtotime($dt));
}



// Format money without useless .00 and with the correct currency code/symbol.
function crmPriceDecimals($conn = null) {
    static $cache = [];
    $account_id = (int)($_SESSION['account_id'] ?? 0);
    if (!$account_id) return 2;
    if (isset($cache[$account_id])) return $cache[$account_id];
    if (!$conn || !columnExists($conn, 'accounts', 'price_decimals')) return $cache[$account_id] = 2;
    $q = $conn->query("SELECT price_decimals FROM accounts WHERE id=$account_id LIMIT 1");
    $dec = ($q && $q->num_rows) ? (int)$q->fetch_assoc()['price_decimals'] : 2;
    return $cache[$account_id] = max(0, min(2, $dec));
}

function crmMoney($amount, $currency='USD', $decimals = null) {
    $currency = strtoupper(trim((string)$currency) ?: 'USD');
    $n = (float)$amount;
    if ($decimals === null) {
        global $conn;
        $decimals = crmPriceDecimals($conn ?? null);
    }
    $decimals = (int)$decimals;
    $out = number_format($n, $decimals);
    if ($currency === 'USD') return '$' . $out;
    if ($currency === 'LBP') return $out . ' LBP';
    if ($currency === 'EUR') return '€' . $out;
    return $out . ' ' . $currency;
}

function crmCampaignSent($row) { return !empty($row['is_sent']) || !empty($row['sent_at']); }

function renderStars($priority, $max = 5) {
    $html = '';
    for ($i = 1; $i <= $max; $i++) {
        $class = $i <= $priority ? 'star filled' : 'star';
        $html .= '<span class="' . $class . '">★</span>';
    }
    return $html;
}

function getUserUploadPath() {
    session_start();
    $user_id = $_SESSION['user_id'] ?? 0;
    $path = rtrim(UPLOAD_DIR, '/\\') . DIRECTORY_SEPARATOR . 'user_' . $user_id . DIRECTORY_SEPARATOR;
    if (!is_dir($path)) {
        mkdir($path, 0755, true);
    }
    return $path;
}

function getUserUploadUrl() {
    session_start();
    $user_id = $_SESSION['user_id'] ?? 0;
    return UPLOAD_URL . 'user_' . $user_id . '/';
}

// ---- Permissions / schema-safe helpers ----
function tableExists($conn, $table) {
    $table = $conn->real_escape_string($table);
    $res = $conn->query("SHOW TABLES LIKE '$table'");
    return $res && $res->num_rows > 0;
}
function columnExists($conn, $table, $column) {
    $table = $conn->real_escape_string($table);
    $column = $conn->real_escape_string($column);
    $res = $conn->query("SHOW COLUMNS FROM `$table` LIKE '$column'");
    return $res && $res->num_rows > 0;
}
function crmPagesConfig() {
    $file = __DIR__ . '/config/pages.php';
    return file_exists($file) ? include $file : [];
}
function currentUserRow($conn, $user_id=null) {
    $uid = $user_id ? (int)$user_id : (int)($_SESSION['user_id'] ?? 0);
    if (!$uid) return null;
    $q = $conn->query("SELECT u.*, r.name role_name, r.permissions role_permissions FROM users u LEFT JOIN roles r ON u.role_id=r.id WHERE u.id=$uid LIMIT 1");
    return ($q && $q->num_rows) ? $q->fetch_assoc() : null;
}
function currentUserIsSuperAdmin($conn, $user_id=null) {
    $u = currentUserRow($conn, $user_id);
    if (!$u) return false;
    if (array_key_exists('is_super_admin', $u) && (int)$u['is_super_admin'] === 1) return true;
    return (int)($u['id'] ?? 0) === 1; // backward compatibility for the first big admin
}
function currentUserIsAccountOwner($conn, $user_id=null) {
    $u = currentUserRow($conn, $user_id);
    if (!$u) return false;
    if (array_key_exists('is_account_owner', $u) && (int)$u['is_account_owner'] === 1) return true;
    $perm = json_decode($u['role_permissions'] ?? '', true);
    return (int)($u['role_id'] ?? 0) === 1 || (!empty($perm['all']));
}
function currentUserIsAdmin($conn) {
    return currentUserIsSuperAdmin($conn) || currentUserIsAccountOwner($conn);
}

function crmPermissionAlias($page) {
    $aliases = [
        'lead' => 'leads',
        'customer' => 'customers',
        'customer_view' => 'customers',
        'add_customer' => 'customers',
        'edit_customer' => 'customers',
        'quotation' => 'quotations',
        'quotation_view' => 'quotations',
        'quotation_invoice' => 'quotations',
        'audience_add' => 'audience',
        'audience_edit' => 'audience',
        'audience_view' => 'audience',
        'campaign_add' => 'campaigns',
        'campaign_edit' => 'campaigns',
        'campaign_view' => 'campaigns',
        'campaign_report' => 'campaigns',
        'occasions' => 'occasions',
    ];
    return $aliases[$page] ?? $page;
}
function userCan($conn, $page, $action='view', $user_id=null) {
    // Page-level permissions only.
    // If a user has access to a page, they get full access inside that page
    // (add/edit/delete/view/actions). No per-action permission details.
    $uid = $user_id ? (int)$user_id : (int)($_SESSION['user_id'] ?? 0);
    if (!$uid) return false;

    // Account owners / admins always have full access.
    if (currentUserIsAdmin($conn)) return true;

    $page = crmPermissionAlias($page);

    // Settings tabs are controlled by settings page access only.
    if (strpos((string)$action, 'tab_') === 0) {
        $action = 'view';
    }

    // Full page access means every action inside the page is allowed.
    $checkPages = [$page];
    if ($page === 'pipeline') $checkPages[] = 'leads';

    if (!tableExists($conn, 'user_permissions')) return false;

    $pageList = "'" . implode("','", array_map(function($v) use ($conn) {
        return $conn->real_escape_string($v);
    }, array_unique($checkPages))) . "'";

    $account_id = (int)($_SESSION['account_id'] ?? 0);
    $q = $conn->query("
        SELECT id
        FROM user_permissions
        WHERE account_id=$account_id
          AND user_id=$uid
          AND allowed=1
          AND action_key='view'
          AND page_key IN ($pageList)
        LIMIT 1
    ");

    return $q && $q->num_rows > 0;
}
function requirePermission($conn, $page, $action='view') {
    if (!userCan($conn, $page, $action)) {
        if (!headers_sent()) { http_response_code(403); }
        if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) || (isset($_SERVER['CONTENT_TYPE']) && stripos($_SERVER['CONTENT_TYPE'], 'application/json') !== false)) {
            jsonResponse(false, 'You do not have permission to open this page.');
        }
        echo '<div class="card" style="padding:22px;margin:18px"><h3>Permission denied</h3><p class="text-muted">You do not have permission to open this page.</p></div>';
        exit;
    }
    return true;
}
function pageAllowed($conn, $page) { return userCan($conn, $page, 'view'); }
function grantFullPermissions($conn, $account_id, $user_id) {
    $account_id=(int)$account_id; $user_id=(int)$user_id;
    if (!tableExists($conn, 'user_permissions')) return;
    $conn->query("DELETE FROM user_permissions WHERE account_id=$account_id AND user_id=$user_id");
    $pages = crmPagesConfig();
    $stmt = $conn->prepare("INSERT INTO user_permissions (account_id,user_id,page_key,action_key,allowed) VALUES (?,?,?,?,1)");
    foreach ($pages as $pageKey=>$cfg) {
        foreach (($cfg['actions'] ?? ['view']) as $actionKey) {
            $stmt->bind_param('iiss', $account_id, $user_id, $pageKey, $actionKey);
            $stmt->execute();
        }
    }
}
function createDefaultStages($conn, $account_id) {
    $account_id=(int)$account_id;
    if (!tableExists($conn, 'stage')) return;
    $exists=$conn->query("SELECT id FROM stage WHERE account_id=$account_id LIMIT 1");
    if ($exists && $exists->num_rows) return;
    $defaults = [
        ['New',1,'#00e5c3',1,0],
        ['In progress',2,'#f59e0b',0,0],
        ['Won',3,'#10b981',0,1],
        ['Lost',4,'#ef4444',0,1],
    ];
    $stmt=$conn->prepare("INSERT INTO stage (name,position,color,is_start,is_end,account_id) VALUES (?,?,?,?,?,?)");
    foreach($defaults as $d){ $stmt->bind_param('sisiii',$d[0],$d[1],$d[2],$d[3],$d[4],$account_id); $stmt->execute(); }
}
