<?php
/* ============================================================================
   WBMCZ — KYC COLLECTED AT CHECKOUT
   ----------------------------------------------------------------------------
   A product no longer shows a dead "KYC Required" button. The buyer presses
   Buy Now like on any shop, and whatever the product still needs is asked for
   on the checkout page as an ordinary form — exactly the way an address is
   asked for elsewhere.

   Two rules run through the whole file:

     1. Anything already saved is LOCKED. It is shown, greyed out, and the
        server ignores it even if the browser sends something else.
     2. Name, mobile and email always come from the registration record. They
        are never editable on a purchase and are copied into the KYC row as is.
   ============================================================================ */

require_once __DIR__ . '/kyc.php';
require_once __DIR__ . '/kyc_fields.php';

if (!function_exists('kycx_account_map')) {

/* KYC column  <=  users column. Fixed at registration, never edited here. */
function kycx_account_map() {
    return [
        'personal.full_name'    => 'name',
        'personal.email'        => 'email',
        'personal.phone_number' => 'mobile',
    ];
}

function kycx_user_type($db, $user_id) {
    static $c = [];
    $k = (int)$user_id;
    if (isset($c[$k])) return $c[$k];
    $t = 'customer';
    try {
        $r = $db->select("SELECT user_type FROM users WHERE id = ?", [$k]);
        if (!empty($r)) $t = (string)$r[0]['user_type'];
    } catch (\Throwable $e) {}
    return $c[$k] = $t;
}

function kycx_user_row($db, $user_id) {
    static $c = [];
    $k = (int)$user_id;
    if (isset($c[$k])) return $c[$k];
    $r = [];
    try { $r = $db->select("SELECT * FROM users WHERE id = ?", [$k]); } catch (\Throwable $e) {}
    return $c[$k] = (!empty($r) ? $r[0] : []);
}

/* Read straight from the table — never through a cached helper, because this
   file writes and then asks again inside the same request. */
function kycx_kyc_row($db, $user_id) {
    kyc_ensure_schema($db);
    $r = [];
    try { $r = $db->select("SELECT * FROM kyc_details WHERE user_id = ?", [(int)$user_id]); } catch (\Throwable $e) {}
    return !empty($r) ? $r[0] : [];
}

function kycx_custom_values($db, $user_id) {
    kycf_ensure_schema($db);
    $out = [];
    try {
        $r = $db->select("SELECT field_id, value, file_path FROM kyc_custom_values WHERE user_id = ?", [(int)$user_id]);
        foreach ($r as $row) {
            $v = trim((string)$row['value']);
            if ($v === '') $v = trim((string)$row['file_path']);
            $out[(int)$row['field_id']] = $v;
        }
    } catch (\Throwable $e) {}
    return $out;
}

function kycx_custom_map($db) {
    static $m = null;
    if ($m !== null) return $m;
    $m = [];
    foreach (kycf_custom_list($db, true) as $c) { $m[(int)$c['id']] = $c; }
    return $m;
}

/* ---------------------------------------------------------------------------
   Everything the basket needs, as single field keys
   --------------------------------------------------------------------------- */
function kycx_required_for_lines($db, $lines, $user_id) {
    if (!function_exists('product_required_kyc')) return [];
    $ut   = kycx_user_type($db, $user_id);
    $keys = [];
    foreach ((array)$lines as $l) {
        $svc = isset($l['svc']) ? $l['svc'] : $l;
        if (empty($svc)) continue;
        $keys = array_merge($keys, product_required_kyc($svc, $ut));
    }
    if (empty($keys)) return [];
    return kycf_expand($db, array_values(array_unique($keys)));
}

/* Which of them are still blank — read fresh, no caching. */
function kycx_missing($db, $user_id, $keys) {
    if (empty($keys)) return [];
    $row    = kycx_kyc_row($db, $user_id);
    $custom = kycx_custom_values($db, $user_id);
    $out    = [];
    foreach ($keys as $key) {
        if (strpos($key, 'custom.') === 0) {
            $fid = (int)substr($key, 7);
            if (empty($custom[$fid])) $out[] = $key;
            continue;
        }
        $parts = explode('.', $key, 2);
        $col   = $parts[1] ?? '';
        if ($col === '') continue;
        if (empty($row[$col])) $out[] = $key;
    }
    return $out;
}

/* ---------------------------------------------------------------------------
   How one key is drawn
   --------------------------------------------------------------------------- */
function kycx_field_def($db, $key) {
    if (strpos($key, 'custom.') === 0) {
        $fid = (int)substr($key, 7);
        $map = kycx_custom_map($db);
        $c   = isset($map[$fid]) ? $map[$fid] : null;
        return [
            'key'    => $key,
            'custom' => $fid,
            'col'    => '',
            'group'  => $c ? (trim((string)$c['group_name']) !== '' ? $c['group_name'] : 'Additional Information') : 'Additional Information',
            'label'  => $c ? (string)$c['field_label'] : $key,
            'type'   => $c ? (string)$c['field_type'] : 'text',
            'opts'   => $c ? array_values(array_filter(array_map('trim', explode(',', (string)$c['options'])))) : [],
            'ph'     => $c ? (string)$c['placeholder'] : '',
            'help'   => $c ? (string)$c['help_text'] : '',
        ];
    }

    $parts = explode('.', $key, 2);
    $sec   = $parts[0];
    $col   = isset($parts[1]) ? $parts[1] : '';
    $b     = kycf_builtin();

    $type = 'text';
    $ph   = '';
    if (in_array($col, kycf_file_fields(), true))                 { $type = 'file'; }
    elseif ($col === 'gender')                                    { $type = 'select'; }
    elseif ($col === 'dob')                                       { $type = 'date'; }
    elseif ($col === 'email' || $col === 'business_email')        { $type = 'email'; }
    elseif ($col === 'aadhar_number')                             { $ph = '1234 5678 9012'; }
    elseif ($col === 'pancard_number')                            { $ph = 'ABCDE1234F'; }
    elseif ($col === 'pincode' || $col === 'biz_pincode')         { $ph = '6 digit pin code'; }
    elseif ($col === 'ifsc_code')                                 { $ph = 'e.g. SBIN0001234'; }
    elseif ($col === 'phone_number' || $col === 'business_phone') { $ph = '10 digit mobile number'; }

    return [
        'key'    => $key,
        'custom' => 0,
        'col'    => $col,
        'group'  => isset($b[$sec]['label']) ? $b[$sec]['label'] : ucfirst($sec),
        'label'  => isset($b[$sec]['fields'][$col]) ? $b[$sec]['fields'][$col] : ucwords(str_replace('_', ' ', $col)),
        'type'   => $type,
        'opts'   => ($col === 'gender') ? ['Male', 'Female', 'Other'] : [],
        'ph'     => $ph,
        'help'   => '',
    ];
}

/* ---------------------------------------------------------------------------
   The block that goes on the checkout page.
   Returns '' when this basket asks for nothing at all.
   --------------------------------------------------------------------------- */
function kycx_render($db, $user_id, $keys) {
    if (empty($keys)) return '';

    $row    = kycx_kyc_row($db, $user_id);
    $custom = kycx_custom_values($db, $user_id);
    $user   = kycx_user_row($db, $user_id);
    $acct   = kycx_account_map();

    /* group the keys the way the KYC wizard groups them */
    $groups = [];
    foreach ($keys as $k) {
        $d = kycx_field_def($db, $k);
        $groups[$d['group']][] = $d;
    }

    $open = 0;   // how many the buyer still has to type
    foreach ($keys as $k) {
        $d = kycx_field_def($db, $k);
        if (isset($acct[$k])) continue;
        if ($d['custom'] > 0) { if (empty($custom[$d['custom']])) $open++; }
        elseif (empty($row[$d['col']]))                            $open++;
    }

    ob_start();
    ?>
    <div class="mt-6 pt-5 border-t border-slate-100">
        <div class="flex items-start gap-3 mb-1">
            <div class="w-9 h-9 rounded-xl bg-amber-50 text-amber-600 flex items-center justify-center flex-shrink-0">
                <i class="fas fa-id-card"></i>
            </div>
            <div class="flex-1 min-w-0">
                <h2 class="font-poppins font-bold text-slate-800">Verification details</h2>
                <p class="text-[12.5px] text-slate-500">
                    <?php if ($open > 0): ?>
                        This service needs the details below. They are saved to your KYC once,
                        and <b>cannot be changed afterwards</b> — so please check them carefully.
                    <?php else: ?>
                        Everything this service needs is already on your KYC. Nothing to fill in.
                    <?php endif; ?>
                </p>
            </div>
        </div>

        <?php foreach ($groups as $gname => $fields): ?>
        <div class="mt-4">
            <p class="text-[11px] font-black uppercase tracking-wide text-slate-400 border-b border-slate-100 pb-1.5 mb-3">
                <?php echo esc($gname); ?>
            </p>
            <div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
                <?php foreach ($fields as $d):
                    $key   = $d['key'];
                    $isAcc = isset($acct[$key]);
                    $saved = $d['custom'] > 0
                           ? (string)($custom[$d['custom']] ?? '')
                           : (string)($row[$d['col']] ?? '');
                    if ($isAcc && $saved === '') { $saved = (string)($user[$acct[$key]] ?? ''); }
                    $locked = ($isAcc || $saved !== '');
                    $wide   = in_array($d['type'], ['textarea'], true);
                ?>
                <div class="<?php echo $wide ? 'sm:col-span-2' : ''; ?>">
                    <label class="lbl">
                        <?php echo esc($d['label']); ?>
                        <?php if ($locked): ?>
                            <span class="ml-1 text-[10px] font-black text-emerald-600 normal-case tracking-normal">
                                <i class="fas fa-lock"></i> <?php echo $isAcc ? 'from your account' : 'saved'; ?>
                            </span>
                        <?php endif; ?>
                    </label>

                    <?php if ($locked): ?>
                        <?php if ($d['type'] === 'file'): ?>
                            <div class="fld bg-slate-50 text-slate-500 flex items-center gap-2">
                                <i class="fas fa-paperclip text-slate-400"></i>
                                <span class="truncate">Document already uploaded</span>
                            </div>
                        <?php else: ?>
                            <input class="fld bg-slate-50 text-slate-500" value="<?php echo esc($saved); ?>" disabled>
                        <?php endif; ?>

                    <?php elseif ($d['type'] === 'file'): ?>
                        <input type="file" name="kxf[<?php echo esc($key); ?>]" accept="image/*,application/pdf"
                               class="fld !py-2 text-[12px]" required>

                    <?php elseif ($d['type'] === 'select'): ?>
                        <select name="kx[<?php echo esc($key); ?>]" class="fld" required>
                            <option value="">— choose —</option>
                            <?php foreach ($d['opts'] as $o): ?>
                                <option value="<?php echo esc($o); ?>"><?php echo esc($o); ?></option>
                            <?php endforeach; ?>
                        </select>

                    <?php elseif ($d['type'] === 'textarea'): ?>
                        <textarea name="kx[<?php echo esc($key); ?>]" rows="3" class="fld"
                                  placeholder="<?php echo esc($d['ph']); ?>" required></textarea>

                    <?php else: ?>
                        <input type="<?php echo in_array($d['type'], ['date', 'email', 'number'], true) ? esc($d['type']) : 'text'; ?>"
                               name="kx[<?php echo esc($key); ?>]" class="fld"
                               placeholder="<?php echo esc($d['ph']); ?>" required>
                    <?php endif; ?>

                    <?php if (!empty($d['help'])): ?>
                        <p class="text-[10.5px] text-slate-400 mt-1"><?php echo esc($d['help']); ?></p>
                    <?php endif; ?>
                </div>
                <?php endforeach; ?>
            </div>
        </div>
        <?php endforeach; ?>

        <p class="text-[11.5px] text-slate-400 mt-4 leading-snug">
            <i class="fas fa-shield-halved"></i>
            These go straight to your KYC record. Locked lines can only be corrected by the office.
        </p>
    </div>
    <?php
    return ob_get_clean();
}

/* Does this basket put any typing in front of the buyer? */
function kycx_has_open_fields($db, $user_id, $keys) {
    if (empty($keys)) return false;
    $acct = kycx_account_map();
    foreach (kycx_missing($db, $user_id, $keys) as $k) {
        if (!isset($acct[$k])) return true;
    }
    return false;
}

/* ---------------------------------------------------------------------------
   Save what the checkout form sent. Locked values are never touched.
   $root = the site root directory (uploads/ lives under it).
   --------------------------------------------------------------------------- */
function kycx_save($db, $user_id, $keys, $root) {
    if (empty($keys)) return ['ok' => true, 'error' => ''];

    kyc_ensure_schema($db);
    kycf_ensure_schema($db);

    $user_id = (int)$user_id;
    $row     = kycx_kyc_row($db, $user_id);
    $custom  = kycx_custom_values($db, $user_id);
    $user    = kycx_user_row($db, $user_id);
    $acct    = kycx_account_map();
    $fileCols= kycf_file_fields();

    $post  = (isset($_POST['kx'])  && is_array($_POST['kx']))  ? $_POST['kx']  : [];
    $kyc_dir   = rtrim($root, '/\\') . '/uploads/kyc';
    $extra_dir = rtrim($root, '/\\') . '/uploads/kyc_extra';

    $set = [];

    foreach ($keys as $key) {

        /* ---- one of the admin's own questions ---- */
        if (strpos($key, 'custom.') === 0) {
            $fid = (int)substr($key, 7);
            if (!empty($custom[$fid])) continue;               // locked
            $map = kycx_custom_map($db);
            $def = isset($map[$fid]) ? $map[$fid] : null;

            if ($def && $def['field_type'] === 'file') {
                $f = kycx_take_file($key, $extra_dir, 'x' . $user_id . '_' . $fid);
                if ($f !== '') { kycf_save_value($db, $user_id, $fid, 'uploads/kyc_extra/' . $f, 'uploads/kyc_extra/' . $f); }
            } else {
                $v = isset($post[$key]) ? sanitize($post[$key]) : '';
                if ($v !== '') { kycf_save_value($db, $user_id, $fid, $v); }
            }
            continue;
        }

        /* ---- a column of kyc_details ---- */
        $parts = explode('.', $key, 2);
        $col   = isset($parts[1]) ? $parts[1] : '';
        if ($col === '') continue;
        if (!empty($row[$col])) continue;                      // locked

        /* name / mobile / email are taken from the registration record and
           nothing the browser sends can change them */
        if (isset($acct[$key])) {
            $v = trim((string)($user[$acct[$key]] ?? ''));
            if ($v !== '') $set[$col] = $v;
            continue;
        }

        if (in_array($col, $fileCols, true)) {
            $f = kycx_take_file($key, $kyc_dir, 'kyc_' . $user_id . '_' . $col);
            if ($f !== '') $set[$col] = $f;
            continue;
        }

        $v = isset($post[$key]) ? sanitize($post[$key]) : '';
        if ($v !== '') $set[$col] = $v;
    }

    if (!empty($set)) {
        try {
            if (!empty($row)) {
                $sets = []; $p = [];
                foreach ($set as $c => $v) { $sets[] = "`$c` = ?"; $p[] = $v; }
                $sets[] = "updated_at = NOW()";
                $p[] = $user_id;
                $db->insert("UPDATE kyc_details SET " . implode(', ', $sets) . " WHERE user_id = ?", $p);
            } else {
                $set['user_id'] = $user_id;
                $set['status']  = 'pending';
                $cols = array_keys($set);
                $ph   = implode(',', array_fill(0, count($cols), '?'));
                $db->insert("INSERT INTO kyc_details (`" . implode('`,`', $cols) . "`) VALUES ($ph)", array_values($set));
            }
        } catch (\Throwable $e) {
            return ['ok' => false, 'error' => 'Your verification details could not be saved. Nothing has been charged.'];
        }
    }

    /* still blank? then the order must not go through */
    $left = kycx_missing($db, $user_id, $keys);
    if (!empty($left)) {
        $labels = [];
        foreach ($left as $k) { $d = kycx_field_def($db, $k); $labels[] = $d['label']; }
        return ['ok' => false, 'error' => 'Please fill in: ' . implode(', ', array_slice($labels, 0, 8))
                                        . (count($labels) > 8 ? ' …' : '') . '.'];
    }
    return ['ok' => true, 'error' => ''];
}

/* One upload out of kxf[...] — returns the stored file name, or '' */
function kycx_take_file($key, $dir, $prefix) {
    if (empty($_FILES['kxf']['name'][$key])) return '';
    if (empty($_FILES['kxf']['tmp_name'][$key]) || !is_uploaded_file($_FILES['kxf']['tmp_name'][$key])) return '';
    $ext = strtolower(pathinfo($_FILES['kxf']['name'][$key], PATHINFO_EXTENSION));
    if (!in_array($ext, ['jpg', 'jpeg', 'png', 'webp', 'pdf'], true)) return '';
    if (!is_dir($dir)) { @mkdir($dir, 0777, true); }
    $name = $prefix . '_' . time() . '.' . $ext;
    if (!move_uploaded_file($_FILES['kxf']['tmp_name'][$key], rtrim($dir, '/\\') . '/' . $name)) return '';
    return $name;
}

/* ---------------------------------------------------------------------------
   Locking, used by the KYC pages themselves
   --------------------------------------------------------------------------- */

/* Column names of kyc_details that already hold a value, plus the three that
   are owned by the registration record and are always locked. */
function kycx_locked_cols($row) {
    $locked = ['full_name', 'email', 'phone_number'];
    foreach ((array)$row as $c => $v) {
        if ($c === 'id' || $c === 'user_id' || $c === 'status' || $c === 'admin_remark'
            || $c === 'created_at' || $c === 'updated_at' || $c === 'same_as_personal') continue;
        if (trim((string)$v) !== '') $locked[] = $c;
    }
    return array_values(array_unique($locked));
}

} // end function_exists guard
