<?php
/**
 * File: includes/jm-telecaller-crm.php
 * Telecaller Collection CRM  |  Shortcode: [jm_telecaller_crm]  |  Passcode: C903TBP
 *
 * v1.2
 * - Single flat pill filter bar (2-row wrap, no scroll):
 *     All Overdue | Upcoming ≤7d | Not Due Yet | PTP Today | Today's Logs
 * - Call Status chips: Connected / Not Reachable / Busy / Call Back Later / Dispute / Number Invalid / Paid
 *   (Promise to Pay removed from call status)
 * - "Promise to Pay" is a separate toggle below notes — 3 date buttons: Today / Tomorrow / Day After
 * - PTP requires call_status = Connected, enforced client + server side
 * - PTP max 2 days ahead enforced server-side
 * - DNC banner + muted buttons for cards with active PTP
 * - Single WhatsApp button (wa.me mobile link)
 */

if ( ! defined( 'ABSPATH' ) ) exit;

// ────────────────────────────────────────────────────────────
// 0. ENQUEUE CSS
// ────────────────────────────────────────────────────────────
add_action( 'wp_enqueue_scripts', function () {
    wp_enqueue_style( 'jm-telecaller-crm',
        plugin_dir_url( dirname( __FILE__ ) ) . 'assets/jm-telecaller-crm.css', [], '1.2' );
} );

// ────────────────────────────────────────────────────────────
// 1. DB TABLE
// ────────────────────────────────────────────────────────────
function jm_crm_install_table() {
    global $wpdb;
    $table = $wpdb->prefix . 'jm_crm_call_logs';
    $sql   = "CREATE TABLE {$table} (
        id             int(11)       NOT NULL AUTO_INCREMENT,
        user_id        bigint(20)    NOT NULL,
        logged_by      varchar(100)  NOT NULL DEFAULT '',
        call_status    varchar(40)   NOT NULL DEFAULT '',
        call_notes     text          NOT NULL,
        promise_date   date          DEFAULT NULL,
        promise_amount decimal(10,2) DEFAULT NULL,
        logged_at      datetime      NOT NULL DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        KEY user_id  (user_id),
        KEY logged_at (logged_at)
    ) " . $wpdb->get_charset_collate() . ";";
    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta( $sql );
}
register_activation_hook(
    WP_PLUGIN_DIR . '/joulemart-pan-verification/joulemart-pan-verification.php',
    'jm_crm_install_table'
);
add_action( 'init', function () {
    if ( get_option( 'jm_crm_db_ver' ) !== '1.2' ) {
        jm_crm_install_table();
        update_option( 'jm_crm_db_ver', '1.2' );
    }
} );

// ────────────────────────────────────────────────────────────
// 2. CORE DATA
// ────────────────────────────────────────────────────────────
function jm_crm_get_collection_data() {
    global $wpdb;
    $t     = $wpdb->prefix . 'jm_transactions';
    $u     = $wpdb->users;
    $um    = $wpdb->usermeta;
    $today = current_time( 'Y-m-d' );

    $rows = $wpdb->get_results( "
        SELECT t.user_id,
            SUM(CASE WHEN t.transaction_type IN ('debit','late_fee') AND t.txn_status='successful' AND t.due_date<'{$today}' THEN t.amount ELSE 0 END) AS past_due,
            SUM(CASE WHEN t.transaction_type IN ('debit','late_fee') AND t.txn_status='successful' THEN t.amount ELSE 0 END) AS total_charges,
            SUM(CASE WHEN t.transaction_type='credit'  AND t.txn_status='successful' THEN t.amount ELSE 0 END) AS total_credits,
            SUM(CASE WHEN t.transaction_type='late_fee' AND t.txn_status='successful' THEN t.amount ELSE 0 END) AS total_lf
        FROM {$t} t GROUP BY t.user_id
        HAVING (total_charges - total_credits) > 0
    ", ARRAY_A );

    if ( empty( $rows ) ) return [ 'overdue' => [], 'upcoming' => [], 'ptp_today' => [] ];

    $ids  = array_column( $rows, 'user_id' );
    $in   = implode( ',', array_map( 'intval', $ids ) );

    // Meta
    $mkeys = [ 'billing_phone', 'master_loan_id', 'credit_limit', '_jm_business_shop_name' ];
    $meta  = [];
    foreach ( $wpdb->get_results(
        "SELECT user_id,meta_key,meta_value FROM {$um} WHERE user_id IN ({$in}) AND meta_key IN ('"
        . implode( "','", $mkeys ) . "')", ARRAY_A ) as $r )
        $meta[ $r['user_id'] ][ $r['meta_key'] ] = $r['meta_value'];

    // Names
    $nm = array_column(
        $wpdb->get_results( "SELECT ID,display_name FROM {$u} WHERE ID IN ({$in})", ARRAY_A ),
        'display_name', 'ID' );

    // FIFO debits
    $dbu = [];
    foreach ( $wpdb->get_results(
        "SELECT user_id,amount,due_date FROM {$t}
         WHERE user_id IN ({$in}) AND transaction_type='debit' AND txn_status='successful'
         ORDER BY user_id,transaction_date,id", ARRAY_A ) as $r )
        $dbu[ $r['user_id'] ][] = $r;

    // Logs
    $lt        = $wpdb->prefix . 'jm_crm_call_logs';
    $last_logs = $active_ptp = $ptp_uids = [];
    if ( $wpdb->get_var( "SHOW TABLES LIKE '{$lt}'" ) ) {
        foreach ( $wpdb->get_results( "
            SELECT l1.* FROM {$lt} l1
            INNER JOIN (SELECT user_id,MAX(logged_at) ma FROM {$lt} GROUP BY user_id) l2
                ON l1.user_id=l2.user_id AND l1.logged_at=l2.ma
            WHERE l1.user_id IN ({$in})", ARRAY_A ) as $r )
            $last_logs[ $r['user_id'] ] = $r;

        foreach ( $wpdb->get_results( $wpdb->prepare(
            "SELECT DISTINCT user_id FROM {$lt} WHERE promise_date=%s", $today ), ARRAY_A ) as $r )
            $ptp_uids[] = (int) $r['user_id'];

        $yest = date( 'Y-m-d', strtotime( '-1 day' ) );
        foreach ( $wpdb->get_results( $wpdb->prepare(
            "SELECT user_id,promise_date FROM {$lt}
             WHERE DATE(logged_at)>=%s AND promise_date>=%s
             ORDER BY logged_at DESC", $yest, $today ), ARRAY_A ) as $r )
            if ( ! isset( $active_ptp[ (int)$r['user_id'] ] ) )
                $active_ptp[ (int)$r['user_id'] ] = $r['promise_date'];

        // Users who had ANY call logged today (any status)
        $called_today_uids = [];
        foreach ( $wpdb->get_results( $wpdb->prepare(
            "SELECT DISTINCT user_id FROM {$lt} WHERE DATE(logged_at) = %s", $today
        ), ARRAY_A ) as $r )
            $called_today_uids[] = (int) $r['user_id'];
    }

    $overdue = $upcoming = [];
    foreach ( $rows as $row ) {
        $uid  = (int)   $row['user_id'];
        $cr   = (float) $row['total_credits'];
        $tc   = (float) $row['total_charges'];
        $pd   = (float) $row['past_due'];
        $lf   = (float) $row['total_lf'];
        $out  = max( 0, $tc - $cr );
        $ovr  = max( 0, $pd - $cr );
        $lfout= max( 0, $lf - max( 0, $cr - ( $tc - $lf ) ) );

        $next_due = 'N/A'; $odays = 0; $days_until = 999;
        if ( isset( $dbu[$uid] ) ) {
            $rem = $cr;
            foreach ( $dbu[$uid] as $d ) {
                $a = (float) $d['amount'];
                if ( $rem >= $a ) { $rem -= $a; continue; }
                $next_due = $d['due_date'];
                if ( $next_due < $today )
                    $odays = (int) floor( ( strtotime($today) - strtotime($next_due) ) / DAY_IN_SECONDS );
                elseif ( $next_due >= $today )
                    $days_until = (int) floor( ( strtotime($next_due) - strtotime($today) ) / DAY_IN_SECONDS );
                break;
            }
        }

        $e = [
            'user_id'    => $uid,
            'name'       => $nm[$uid] ?? "User {$uid}",
            'shop'       => $meta[$uid]['_jm_business_shop_name'] ?? '',
            'phone'      => $meta[$uid]['billing_phone']          ?? '',
            'loan_id'    => $meta[$uid]['master_loan_id']         ?? 'N/A',
            'climit'     => (float)( $meta[$uid]['credit_limit']  ?? 0 ),
            'outstanding'=> $out,
            'overdue_amt'=> $ovr,
            'lf_out'     => $lfout,
            'next_due'   => $next_due,
            'odays'      => $odays,
            'days_until' => $days_until,
            'last_log'     => $last_logs[$uid] ?? null,
            'dnc'          => isset( $active_ptp[$uid] ),
            'ptp_date'     => $active_ptp[$uid] ?? null,
            'ptp_today'    => in_array( $uid, $ptp_uids ),
            'called_today' => in_array( $uid, $called_today_uids ?? [] ),
        ];

        if ( $ovr > 0 ) $overdue[]  = $e;
        else            $upcoming[] = $e;
    }

    usort( $overdue,  fn($a,$b) => $b['odays']      <=> $a['odays'] );
    usort( $upcoming, fn($a,$b) => strcmp( $a['next_due'], $b['next_due'] ) );

    return [
        'overdue'   => $overdue,
        'upcoming'  => $upcoming,
        'ptp_today' => array_values( array_filter(
            array_merge( $overdue, $upcoming ), fn($e) => $e['ptp_today'] ) ),
    ];
}

// ────────────────────────────────────────────────────────────
// 3. AJAX — save log
// ────────────────────────────────────────────────────────────
add_action( 'wp_ajax_jm_crm_save_log',        'jm_crm_ajax_save_log' );
add_action( 'wp_ajax_nopriv_jm_crm_save_log', 'jm_crm_ajax_save_log' );
function jm_crm_ajax_save_log() {
    if ( session_status() === PHP_SESSION_NONE ) session_start();
    if ( empty( $_SESSION['jm_crm_auth'] ) ) wp_send_json_error( 'Not authenticated', 403 );
    check_ajax_referer( 'jm_crm_nonce', 'nonce' );

    global $wpdb;
    $uid    = absint( $_POST['user_id']      ?? 0 );
    $status = sanitize_text_field( $_POST['call_status']   ?? '' );
    $notes  = sanitize_textarea_field( $_POST['call_notes'] ?? '' );
    $pdate  = sanitize_text_field( $_POST['promise_date']  ?? '' );
    $pamt   = floatval( $_POST['promise_amount'] ?? 0 );
    $by     = sanitize_text_field( $_POST['logged_by']     ?? 'Telecaller' );

    if ( ! $uid || ! $status ) wp_send_json_error( 'Missing fields' );

    // PTP only valid if connected
    if ( $pdate && $status !== 'Connected' )
        wp_send_json_error( 'Promise to Pay can only be set when call status is Connected.' );

    if ( $pdate ) {
        $today    = current_time( 'Y-m-d' );
        $max_date = date( 'Y-m-d', strtotime( '+2 days', strtotime( $today ) ) );
        if ( $pdate < $today || $pdate > $max_date )
            wp_send_json_error( 'Promise date must be today, tomorrow, or day after tomorrow.' );
    }

    $data = [ 'user_id'=>$uid,'logged_by'=>$by,'call_status'=>$status,
              'call_notes'=>$notes,'logged_at'=>current_time('mysql') ];
    $fmt  = [ '%d','%s','%s','%s','%s' ];
    if ( $pdate ) { $data['promise_date']   = $pdate; $fmt[] = '%s'; }
    if ( $pamt  ) { $data['promise_amount'] = $pamt;  $fmt[] = '%f'; }

    $wpdb->insert( $wpdb->prefix . 'jm_crm_call_logs', $data, $fmt );
    wp_send_json_success( [ 'id' => $wpdb->insert_id ] );
}

// ────────────────────────────────────────────────────────────
// 4. AJAX — get history
// ────────────────────────────────────────────────────────────
add_action( 'wp_ajax_jm_crm_get_history',        'jm_crm_ajax_get_history' );
add_action( 'wp_ajax_nopriv_jm_crm_get_history', 'jm_crm_ajax_get_history' );
function jm_crm_ajax_get_history() {
    if ( session_status() === PHP_SESSION_NONE ) session_start();
    if ( empty( $_SESSION['jm_crm_auth'] ) ) wp_send_json_error( 'Not authenticated', 403 );
    check_ajax_referer( 'jm_crm_nonce', 'nonce' );
    global $wpdb;
    $rows = $wpdb->get_results( $wpdb->prepare(
        "SELECT * FROM {$wpdb->prefix}jm_crm_call_logs WHERE user_id=%d ORDER BY logged_at DESC LIMIT 20",
        absint( $_GET['user_id'] ?? 0 ) ), ARRAY_A );
    wp_send_json_success( $rows );
}

// ────────────────────────────────────────────────────────────
// 5a. AJAX — search customers (admin history lookup)
// FIX: use wpdb->prepare() correctly; use jm_crm_admin_nonce
// ────────────────────────────────────────────────────────────
add_action( 'wp_ajax_jm_crm_search_customers', 'jm_crm_ajax_search_customers' );
function jm_crm_ajax_search_customers() {
    if ( ! current_user_can('manage_options') ) wp_send_json_error('Forbidden', 403);
    check_ajax_referer('jm_crm_admin_nonce','nonce');

    global $wpdb;
    $raw = sanitize_text_field( $_GET['q'] ?? '' );
    if ( strlen( $raw ) < 2 ) wp_send_json_success( [] );

    $like = '%' . $wpdb->esc_like( $raw ) . '%';
    $lt   = $wpdb->prefix . 'jm_crm_call_logs';

    $rows = $wpdb->get_results( $wpdb->prepare("
        SELECT DISTINCT l.user_id,
               u.display_name,
               um_p.meta_value AS phone,
               um_l.meta_value AS loan_id,
               um_s.meta_value AS shop
        FROM {$lt} l
        LEFT JOIN {$wpdb->users}    u    ON l.user_id = u.ID
        LEFT JOIN {$wpdb->usermeta} um_p ON l.user_id = um_p.user_id AND um_p.meta_key = 'billing_phone'
        LEFT JOIN {$wpdb->usermeta} um_l ON l.user_id = um_l.user_id AND um_l.meta_key = 'master_loan_id'
        LEFT JOIN {$wpdb->usermeta} um_s ON l.user_id = um_s.user_id AND um_s.meta_key = '_jm_business_shop_name'
        WHERE ( u.display_name  LIKE %s
             OR um_p.meta_value LIKE %s
             OR um_l.meta_value LIKE %s )
        LIMIT 12
    ", $like, $like, $like ) );

    wp_send_json_success( array_map( fn($r) => [
        'user_id' => (int) $r->user_id,
        'name'    => $r->display_name ?? "User {$r->user_id}",
        'phone'   => $r->phone   ?? '',
        'loan_id' => $r->loan_id ?? '',
        'shop'    => $r->shop    ?? '',
    ], $rows ) );
}

// ────────────────────────────────────────────────────────────
// 5b. AJAX — full customer history with optional date range
// ────────────────────────────────────────────────────────────
add_action( 'wp_ajax_jm_crm_customer_history', 'jm_crm_ajax_customer_history' );
function jm_crm_ajax_customer_history() {
    if ( ! current_user_can('manage_options') ) wp_send_json_error('Forbidden', 403);
    check_ajax_referer('jm_crm_admin_nonce','nonce');

    global $wpdb;
    $uid      = absint( $_GET['user_id'] ?? 0 );
    $date_from= sanitize_text_field( $_GET['date_from'] ?? '' );
    $date_to  = sanitize_text_field( $_GET['date_to']   ?? '' );
    if ( ! $uid ) wp_send_json_error('Missing user_id');

    $lt    = $wpdb->prefix . 'jm_crm_call_logs';
    $where = 'WHERE user_id = %d';
    $args  = [ $uid ];

    if ( $date_from ) {
        $where .= ' AND logged_at >= %s';
        $args[] = $date_from . ' 00:00:00';
    }
    if ( $date_to ) {
        $where .= ' AND logged_at <= %s';
        $args[] = $date_to . ' 23:59:59';
    }

    $logs = $wpdb->get_results(
        $wpdb->prepare( "SELECT * FROM {$lt} {$where} ORDER BY logged_at DESC", ...$args ),
        ARRAY_A
    );

    $meta = [];
    foreach ( $wpdb->get_results( $wpdb->prepare(
        "SELECT meta_key, meta_value FROM {$wpdb->usermeta}
         WHERE user_id = %d AND meta_key IN ('billing_phone','master_loan_id','_jm_business_shop_name','credit_limit')",
        $uid ), ARRAY_A ) as $r )
        $meta[ $r['meta_key'] ] = $r['meta_value'];

    wp_send_json_success([
        'logs' => $logs,
        'meta' => [
            'phone'  => $meta['billing_phone']          ?? '',
            'loan_id'=> $meta['master_loan_id']         ?? '',
            'shop'   => $meta['_jm_business_shop_name'] ?? '',
            'limit'  => $meta['credit_limit']           ?? '',
        ],
    ]);
}

// ────────────────────────────────────────────────────────────
// 6. SHORTCODE
// ────────────────────────────────────────────────────────────
add_shortcode( 'jm_telecaller_crm', 'jm_render_telecaller_crm' );
function jm_render_telecaller_crm() {
    if ( session_status() === PHP_SESSION_NONE ) session_start();
    if ( isset( $_POST['jm_crm_passcode'] ) )
        $_SESSION['jm_crm_auth'] = ( $_POST['jm_crm_passcode'] === 'C903TBP' );
    if ( isset( $_GET['jm_crm_logout'] ) )
        $_SESSION['jm_crm_auth'] = false;

    ob_start();

    /* ── LOGIN ───────────────────────────────────────────────────────── */
    if ( empty( $_SESSION['jm_crm_auth'] ) ) { ?>
        <div id="jm-crm-login"><div class="jm-crm-login-box">
            <div class="crm-login-icon">📞</div>
            <h2>Collection CRM</h2><p>Enter your passcode to continue</p>
            <form method="post">
                <input type="password" name="jm_crm_passcode" placeholder="Passcode" autocomplete="off" autofocus>
                <?php if ( isset( $_POST['jm_crm_passcode'] ) ): ?><p class="crm-login-err">❌ Incorrect passcode.</p><?php endif; ?>
                <button type="submit">Unlock</button>
            </form>
        </div></div>
        <style>
        #jm-crm-login{display:flex;align-items:center;justify-content:center;min-height:80vh;background:#0d0d0d}
        .jm-crm-login-box{background:#1a1a1a;border:1px solid #2a2a2a;border-radius:16px;padding:48px 40px;text-align:center;width:100%;max-width:360px}
        .crm-login-icon{font-size:48px;margin-bottom:16px}
        .jm-crm-login-box h2{color:#fff;margin:0 0 8px;font-size:24px}
        .jm-crm-login-box p{color:#888;margin:0 0 28px;font-size:14px}
        .jm-crm-login-box input{width:100%;padding:14px;border-radius:10px;border:1px solid #333;background:#111;color:#fff;font-size:18px;box-sizing:border-box;margin-bottom:14px;text-align:center;letter-spacing:5px}
        .jm-crm-login-box input:focus{outline:none;border-color:#e63946}
        .jm-crm-login-box button{width:100%;padding:14px;background:#e63946;color:#fff;border:none;border-radius:10px;font-size:16px;font-weight:700;cursor:pointer}
        .crm-login-err{color:#e63946;font-size:13px;margin-top:10px}
        </style>
    <?php return ob_get_clean(); }

    /* ── AUTHENTICATED ───────────────────────────────────────────────── */
    $data      = jm_crm_get_collection_data();
    $overdue   = $data['overdue'];
    $upcoming  = $data['upcoming'];
    $ptp_today = $data['ptp_today'];
    $today     = current_time( 'Y-m-d' );
    $tmrw      = date( 'Y-m-d', strtotime( '+1 day', strtotime( $today ) ) );
    $daft      = date( 'Y-m-d', strtotime( '+2 days', strtotime( $today ) ) );
    $today_d   = date( 'd', strtotime($today) );
    $tmrw_d    = date( 'd', strtotime($tmrw) );
    $daft_d    = date( 'd', strtotime($daft) );
    $mon_yr    = date( 'M Y', strtotime($today) ); // same month for all 3

    $urg    = array_values( array_filter( $upcoming, fn($c)=>$c['days_until']<=7 ) );
    $notdue = array_values( array_filter( $upcoming, fn($c)=>$c['days_until']>7 ) );

    wp_enqueue_script( 'jquery' );
    $nonce = wp_create_nonce( 'jm_crm_nonce' );
    $ajax  = admin_url( 'admin-ajax.php' );

    // Counts for filter pills
    $cnt_overdue = count($overdue);
    $cnt_urg     = count($urg);
    $cnt_notdue  = count($notdue);
    $cnt_ptp     = count($ptp_today);
    ?>

<div id="jm-crm-wrap">

<!-- TOPBAR -->
<div class="crm-topbar">
    <div class="crm-tb-left">
        <span class="crm-logo">📞 Collection CRM</span>
        <span class="crm-today-date"><?php echo date('D, d M Y', strtotime($today)); ?></span>
    </div>
    <div class="crm-tb-right">
        <div class="crm-kpi kpi-red"><span><?php echo $cnt_overdue; ?></span><small>Overdue</small></div>
        <div class="crm-kpi kpi-red"><span>₹<?php echo number_format(array_sum(array_column($overdue,'overdue_amt')),0); ?></span><small>Overdue ₹</small></div>
        <div class="crm-kpi"><span><?php echo $cnt_urg; ?></span><small>Due ≤7d</small></div>
        <?php if($cnt_ptp): ?><div class="crm-kpi kpi-ptp"><span><?php echo $cnt_ptp; ?></span><small>PTP Today</small></div><?php endif; ?>
        <!-- Settings toggle: hide called-today customers -->
        <div class="crm-setting-wrap" title="When ON, customers already called today won't appear in the list">
            <label class="crm-toggle-label" for="hide-called-toggle">
                <span class="crm-toggle-txt">Hide called today</span>
                <div class="crm-toggle">
                    <input type="checkbox" id="hide-called-toggle">
                    <span class="crm-toggle-slider"></span>
                </div>
            </label>
        </div>
        <a href="?jm_crm_logout=1" class="crm-logout-btn">Logout</a>
    </div>
</div>

<!-- FILTER PILLS — flat 2-row wrap, no scroll -->
<div class="crm-filter-bar">
    <button class="crm-pill active" data-filter="overdue">🔴 Overdue <em><?php echo $cnt_overdue; ?></em></button>
    <button class="crm-pill" data-filter="urgent">🟡 Upcoming ≤7 days <em><?php echo $cnt_urg; ?></em></button>
    <button class="crm-pill" data-filter="notdue">📆 Not Due Yet <em><?php echo $cnt_notdue; ?></em></button>
    <?php if($cnt_ptp): ?><button class="crm-pill crm-pill-ptp" data-filter="ptp">🤝 PTP Today <em><?php echo $cnt_ptp; ?></em></button><?php endif; ?>
    <button class="crm-pill" data-filter="logs">📋 Today's Logs</button>
</div>

<!-- SEARCH -->
<div class="crm-search-wrap">
    <input type="text" id="crm-search" placeholder="🔍  Search name · phone · loan ID">
</div>

<?php
// ── Card renderer closure ──────────────────────────────────────────────
$card = function( array $c, string $ctx ) use ($today) {
    $uid  = $c['user_id'];
    $nm   = esc_js($c['name']);
    $ph   = esc_js($c['phone']);
    $dnc  = $c['dnc'];
    $last = $c['last_log'];

    // WhatsApp message varies by context
    if ( $ctx === 'overdue' ) {
        $wa_body = "Reminder: Your JouleMart Credit Line payment of ₹".number_format($c['overdue_amt'],0)." is overdue by {$c['odays']} day(s). Loan ID: {$c['loan_id']}. Please pay immediately to avoid further late fees. Pay now: https://credit.joulemart.in/repayment";
        $left_badge = $c['odays']>30?'badge-red':($c['odays']>7?'badge-orange':'badge-yellow');
        $left_txt   = $c['odays'].'d overdue';
    } elseif ( $ctx === 'ptp' ) {
        $pamt = ($last && $last['promise_amount']) ? $last['promise_amount'] : $c['overdue_amt'];
        $wa_body = "Hi {$c['name']}, as promised please pay ₹".number_format($pamt,0)." today. Loan ID: {$c['loan_id']}. Pay here: https://credit.joulemart.in/repayment";
        $left_badge = 'badge-ptp';
        $left_txt   = '🤝 PTP Today';
    } else {
        $due_fmt = $c['next_due'] !== 'N/A' ? date('d M Y', strtotime($c['next_due'])) : 'N/A';
        $wa_body = "Dear {$c['name']}, your JouleMart Credit Line payment of ₹".number_format($c['outstanding'],0)." is due on {$due_fmt}. Loan ID: {$c['loan_id']}. Please pay on time. Pay here: https://credit.joulemart.in/repayment";
        $du = $c['days_until'];
        $left_badge = $du<=2?'badge-orange':($du<=7?'badge-yellow':'badge-green');
        $left_txt   = 'Due in '.$du.'d';
    }
    $wa_link = 'https://wa.me/91'.$c['phone'].'?text='.rawurlencode($wa_body);
    $called_today = $c['called_today'] ?? false;
    $card_cls     = 'crm-card crm-card-'.$ctx.($dnc?' crm-card-dnc':($called_today?' crm-card-called':''));
    ?>
    <div class="<?php echo $card_cls; ?>"
         data-search="<?php echo esc_attr(strtolower($c['name'].' '.$c['phone'].' '.$c['loan_id'].' '.$c['shop'])); ?>"
         data-called="<?php echo $called_today ? '1' : '0'; ?>">

        <?php if($dnc): ?>
        <div class="crm-dnc-bar">
            🤝 Promise to Pay on <?php echo date('d M', strtotime($c['ptp_date'])); ?> — Do not disturb today
        </div>
        <?php elseif($called_today): ?>
        <div class="crm-called-bar">
            ✅ Called today
            <?php if($last): ?> — <strong><?php echo esc_html($last['call_status']); ?></strong> at <?php echo date('H:i', strtotime($last['logged_at'])); ?><?php endif; ?>
        </div>
        <?php endif; ?>

        <div class="crm-card-head">
            <div class="crm-card-name">
                <strong><?php echo esc_html($c['name']); ?></strong>
                <?php if($c['shop']): ?><small><?php echo esc_html($c['shop']); ?></small><?php endif; ?>
            </div>
            <div class="crm-card-pills">
                <span class="badge <?php echo $left_badge; ?>"><?php echo $left_txt; ?></span>
                <?php if($dnc): ?><span class="badge badge-ptp">PTP Active</span>
                <?php elseif($last): ?><span class="badge badge-grey">📋 <?php echo esc_html($last['call_status']); ?></span><?php endif; ?>
            </div>
        </div>

        <div class="crm-card-meta">
            <span>📋 <?php echo esc_html($c['loan_id']); ?></span>
            <span>📱 <?php echo esc_html($c['phone']); ?></span>
            <?php if($ctx==='overdue'): ?>
                <span>📅 Was due: <?php echo $c['next_due']!=='N/A'?date('d M Y',strtotime($c['next_due'])):'N/A'; ?></span>
            <?php elseif($ctx!=='ptp'): ?>
                <span>📅 Due: <strong><?php echo $c['next_due']!=='N/A'?date('d M Y',strtotime($c['next_due'])):'N/A'; ?></strong></span>
            <?php endif; ?>
        </div>

        <div class="crm-card-amts">
            <?php if($ctx==='overdue'||$ctx==='ptp'): ?>
            <div class="camt camt-red"><small>Overdue</small><strong>₹<?php echo number_format($c['overdue_amt'],2); ?></strong></div>
            <?php endif; ?>
            <?php if($c['lf_out']>0): ?>
            <div class="camt camt-red"><small>Late Fees</small><strong>₹<?php echo number_format($c['lf_out'],2); ?></strong></div>
            <?php endif; ?>
            <div class="camt"><small>Total Outstanding</small><strong>₹<?php echo number_format($c['outstanding'],2); ?></strong></div>
            <?php if($ctx==='urgent'||$ctx==='notdue'): ?>
            <div class="camt"><small>Credit Limit</small><strong>₹<?php echo number_format($c['climit'],0); ?></strong></div>
            <?php endif; ?>
            <?php if($ctx==='ptp'&&$last&&$last['promise_amount']): ?>
            <div class="camt camt-ptp"><small>Promised Amt</small><strong>₹<?php echo number_format($last['promise_amount'],0); ?></strong></div>
            <?php endif; ?>
        </div>

        <div class="crm-card-actions">
            <a href="tel:<?php echo esc_attr($c['phone']); ?>" class="cbtn cbtn-call<?php echo $dnc?' cbtn-muted':''; ?>">📞 Call<?php echo $ctx==='ptp'?' Follow-up':''; ?></a>
            <a href="<?php echo $wa_link; ?>" target="_blank" class="cbtn cbtn-wa<?php echo $dnc?' cbtn-muted':''; ?>">💬 WhatsApp</a>
            <button class="cbtn cbtn-log" onclick="openLogModal(<?php echo $uid; ?>,'<?php echo $nm; ?>','<?php echo $ph; ?>')">📝 Log</button>
            <button class="cbtn cbtn-hist" onclick="openHistory(<?php echo $uid; ?>,'<?php echo $nm; ?>')">🕐 History</button>
        </div>

        <?php if($last): ?>
        <div class="crm-last-log">
            <span class="ldot ldot-<?php echo sanitize_html_class($last['call_status']); ?>"></span>
            <strong><?php echo esc_html($last['call_status']); ?></strong>
            <?php if(trim($last['call_notes'])): ?> — <?php echo esc_html(wp_trim_words($last['call_notes'],12,'…')); ?><?php endif; ?>
            <?php if($last['promise_date']): ?> · 🤝 <strong><?php echo date('d M',strtotime($last['promise_date'])); ?></strong><?php if($last['promise_amount']): ?> ₹<?php echo number_format($last['promise_amount'],0); ?><?php endif; ?><?php endif; ?>
            <span class="ltime"><?php echo date('d M, H:i',strtotime($last['logged_at'])); ?></span>
        </div>
        <?php endif; ?>
    </div>
<?php }; // end $card closure

/* ── PANEL: OVERDUE ──────────────────────────────────────────────────── */
?>
<div class="crm-panel active" id="panel-overdue">
<?php if(empty($overdue)): ?><div class="crm-empty">✅ No overdue accounts</div>
<?php else: echo '<div class="crm-cards">'; foreach($overdue as $c) $card($c,'overdue'); echo '</div>'; endif; ?>
</div>

<!-- ── PANEL: UPCOMING URGENT ──────────────────────────────────────── -->
<div class="crm-panel" id="panel-urgent">
<?php if(empty($urg)): ?><div class="crm-empty">No accounts due in the next 7 days</div>
<?php else: echo '<div class="crm-cards">'; foreach($urg as $c) $card($c,'urgent'); echo '</div>'; endif; ?>
</div>

<!-- ── PANEL: NOT DUE YET ──────────────────────────────────────────── -->
<div class="crm-panel" id="panel-notdue">
<?php if(empty($notdue)): ?><div class="crm-empty">No accounts in this category</div>
<?php else: echo '<div class="crm-cards">'; foreach($notdue as $c) $card($c,'notdue'); echo '</div>'; endif; ?>
</div>

<!-- ── PANEL: PTP TODAY ────────────────────────────────────────────── -->
<?php if($cnt_ptp): ?>
<div class="crm-panel" id="panel-ptp">
    <div class="crm-ptp-header">
        <span>🤝 <?php echo $cnt_ptp; ?> customer<?php echo $cnt_ptp>1?'s':''; ?> promised to pay today</span>
        <strong>Expected ₹<?php echo number_format(array_sum(array_column($ptp_today,'overdue_amt')),0); ?>+</strong>
    </div>
    <div class="crm-cards"><?php foreach($ptp_today as $c) $card($c,'ptp'); ?></div>
</div>
<?php endif; ?>

<!-- ── PANEL: TODAY'S LOGS ─────────────────────────────────────────── -->
<div class="crm-panel" id="panel-logs">
<?php
global $wpdb;
$lt   = $wpdb->prefix.'jm_crm_call_logs';
$tlogs= [];
if($wpdb->get_var("SHOW TABLES LIKE '{$lt}'")){
    $ts = current_time('Y-m-d').' 00:00:00';
    $te = current_time('Y-m-d').' 23:59:59';
    $tlogs=$wpdb->get_results($wpdb->prepare(
        "SELECT l.*,u.display_name,um.meta_value AS phone FROM {$lt} l
         LEFT JOIN {$wpdb->users} u ON l.user_id=u.ID
         LEFT JOIN {$wpdb->usermeta} um ON l.user_id=um.user_id AND um.meta_key='billing_phone'
         WHERE l.logged_at BETWEEN %s AND %s ORDER BY l.logged_at DESC",$ts,$te), ARRAY_A);
}
?>
<?php if(empty($tlogs)): ?><div class="crm-empty">No calls logged today yet.</div>
<?php else: ?>
<div class="crm-log-chips">
    <?php $sc=array_count_values(array_column($tlogs,'call_status')); arsort($sc);
    foreach($sc as $s=>$n): ?><div class="lchip lchip-<?php echo sanitize_html_class($s); ?>"><strong><?php echo $n; ?></strong> <?php echo esc_html($s); ?></div><?php endforeach; ?>
</div>
<div class="crm-log-scroll">
<table class="crm-log-tbl">
    <thead><tr><th>Time</th><th>Customer</th><th>Phone</th><th>Status</th><th>Notes</th><th>PTP</th><th>Amt</th><th>By</th></tr></thead>
    <tbody>
    <?php foreach($tlogs as $l): ?>
    <tr>
        <td><?php echo date('H:i',strtotime($l['logged_at'])); ?></td>
        <td><?php echo esc_html($l['display_name']??"User {$l['user_id']}"); ?></td>
        <td><?php echo esc_html($l['phone']??''); ?></td>
        <td><span class="bpill lchip-<?php echo sanitize_html_class($l['call_status']); ?>"><?php echo esc_html($l['call_status']); ?></span></td>
        <td><?php echo esc_html(wp_trim_words($l['call_notes'],12,'…')); ?></td>
        <td><?php echo $l['promise_date']?date('d M',strtotime($l['promise_date'])):'—'; ?></td>
        <td><?php echo $l['promise_amount']?'₹'.number_format($l['promise_amount'],0):'—'; ?></td>
        <td><?php echo esc_html($l['logged_by']); ?></td>
    </tr>
    <?php endforeach; ?>
    </tbody>
</table>
</div>
<?php endif; ?>
</div>

</div><!-- #jm-crm-wrap -->

<!-- ════════════ MODAL: LOG CALL ════════════════════════════════════════ -->
<div id="modal-log" class="crm-overlay" style="display:none">
<div class="crm-modal">
    <div class="crm-mhead">
        <h3>📝 Log Call — <span id="mlog-cname"></span></h3>
        <button onclick="closeLog()">✕</button>
    </div>
    <div class="crm-mbody">
        <input type="hidden" id="mlog-uid">

        <div class="mform-row">
            <label>Telecaller Name</label>
            <input type="text" id="mlog-by" value="<?php echo esc_attr(wp_get_current_user()->display_name ?: 'Telecaller'); ?>">
        </div>

        <div class="mform-row">
            <label>Call Status <span class="mreq">*</span></label>
            <div class="status-chips">
                <?php foreach(['Connected','Not Reachable','Busy','Call Back Later','Dispute','Number Invalid','Paid'] as $s): ?>
                <button type="button" class="sc" data-v="<?php echo esc_attr($s); ?>"><?php echo esc_html($s); ?></button>
                <?php endforeach; ?>
            </div>
            <input type="hidden" id="mlog-status">
        </div>

        <div class="mform-row">
            <label>Call Notes</label>
            <textarea id="mlog-notes" rows="3" placeholder="What did the customer say?"></textarea>
        </div>

        <!-- PTP section — shown only when Connected -->
        <div id="ptp-section" style="display:none">
            <div class="ptp-divider"><span>Promise to Pay</span></div>
            <div class="ptp-date-row">
                <button type="button" class="ptp-day" data-d="<?php echo $today; ?>">
                    <span class="ptp-num"><?php echo $today_d; ?></span>
                    <span class="ptp-mon"><?php echo $mon_yr; ?></span>
                    <span class="ptp-label">Today</span>
                </button>
                <button type="button" class="ptp-day" data-d="<?php echo $tmrw; ?>">
                    <span class="ptp-num"><?php echo $tmrw_d; ?></span>
                    <span class="ptp-mon"><?php echo $mon_yr; ?></span>
                    <span class="ptp-label">Tomorrow</span>
                </button>
                <button type="button" class="ptp-day" data-d="<?php echo $daft; ?>">
                    <span class="ptp-num"><?php echo $daft_d; ?></span>
                    <span class="ptp-mon"><?php echo $mon_yr; ?></span>
                    <span class="ptp-label">Day After</span>
                </button>
            </div>
            <input type="hidden" id="mlog-pdate">
            <div class="mform-row" style="margin-top:12px">
                <label>Promise Amount <span style="font-weight:400;color:#666">(optional)</span></label>
                <input type="number" id="mlog-pamt" placeholder="₹ Amount" min="0" step="100">
            </div>
        </div>

        <div class="mform-err" id="mlog-err"></div>
    </div>
    <div class="crm-mfoot">
        <button class="cbtn cbtn-secondary" onclick="closeLog()">Cancel</button>
        <button class="cbtn cbtn-save" id="mlog-save" onclick="saveLog()">Save Log</button>
    </div>
</div>
</div>

<!-- ════════════ MODAL: HISTORY ═════════════════════════════════════════ -->
<div id="modal-hist" class="crm-overlay" style="display:none">
<div class="crm-modal crm-modal-wide">
    <div class="crm-mhead">
        <h3>🕐 Call History — <span id="mhist-cname"></span></h3>
        <button onclick="closeHist()">✕</button>
    </div>
    <div class="crm-mbody" id="mhist-body"><div class="crm-spinner">Loading…</div></div>
</div>
</div>

<script>
(function($){
    const AJ='<?php echo $ajax; ?>', NK='<?php echo $nonce; ?>';

    // ── Hide-called-today toggle ─────────────────────────────────────────
    const HIDE_KEY = 'jm_crm_hide_called';
    const hideTgl  = document.getElementById('hide-called-toggle');
    let   hideActive = localStorage.getItem(HIDE_KEY) === '1';

    function applyHideFilter(){
        hideTgl.checked = hideActive;
        document.querySelectorAll('.crm-card[data-called="1"]').forEach(card => {
            // Only hide if search doesn't have an active query
            if(hideActive) card.style.display = 'none';
            else if(card.style.display === 'none') card.style.display = '';
        });
        const txt = hideTgl.closest('.crm-toggle-label') && hideTgl.closest('.crm-toggle-label').querySelector('.crm-toggle-txt');
        if(txt) txt.textContent = hideActive ? 'Show called today' : 'Hide called today';
    }
    applyHideFilter(); // run on page load

    hideTgl.addEventListener('change', function(){
        hideActive = this.checked;
        localStorage.setItem(HIDE_KEY, hideActive ? '1' : '0');
        applyHideFilter();
    });

    // ── Filter pills ──────────────────────────────────────────────────────
    $('.crm-pill').on('click', function(){
        $('.crm-pill').removeClass('active');
        $(this).addClass('active');
        $('.crm-panel').removeClass('active');
        $('#panel-'+$(this).data('filter')).addClass('active');
        $('#crm-search').val('').trigger('input');
        setTimeout(applyHideFilter, 50); // re-apply after panel swap
    });

    // ── Search ────────────────────────────────────────────────────────────
    $('#crm-search').on('input', function(){
        const q=$(this).val().toLowerCase().trim();
        $('.crm-panel.active .crm-card').each(function(){
            // Search overrides hide — show card if it matches query even if called today
            const matches = !q||($(this).data('search')||'').includes(q);
            const isCalledHidden = hideActive && $(this).data('called') == '1' && !q;
            $(this).toggle(matches && !isCalledHidden);
        });
    });

    // ── Call status chips ─────────────────────────────────────────────────
    $(document).on('click','.sc',function(){
        $('.sc').removeClass('active');
        $(this).addClass('active');
        const v=$(this).data('v');
        $('#mlog-status').val(v);
        // Show PTP section only when Connected
        if(v==='Connected') {
            $('#ptp-section').slideDown(180);
        } else {
            $('#ptp-section').slideUp(180);
            $('#mlog-pdate').val('');
            $('.ptp-day').removeClass('active');
        }
    });

    // ── PTP date buttons ──────────────────────────────────────────────────
    $(document).on('click','.ptp-day',function(){
        $('.ptp-day').removeClass('active');
        $(this).addClass('active');
        $('#mlog-pdate').val($(this).data('d'));
    });

    // ── Log modal ─────────────────────────────────────────────────────────
    window.openLogModal=function(uid,name,phone){
        $('#mlog-uid').val(uid);
        $('#mlog-cname').text(name+(phone?' · '+phone:''));
        $('#mlog-status,#mlog-notes,#mlog-pdate,#mlog-pamt').val('');
        $('#mlog-err').text('');
        $('.sc').removeClass('active');
        $('.ptp-day').removeClass('active');
        $('#ptp-section').hide();
        $('#modal-log').fadeIn(150);
    };
    window.closeLog=function(){$('#modal-log').fadeOut(150);};

    window.saveLog=function(){
        const uid=    $('#mlog-uid').val();
        const status= $('#mlog-status').val();
        const notes=  $('#mlog-notes').val().trim();
        const by=     $('#mlog-by').val().trim()||'Telecaller';
        const pdate=  $('#mlog-pdate').val();
        const pamt=   $('#mlog-pamt').val();
        if(!status){$('#mlog-err').text('Please select a call status.');return;}
        $('#mlog-save').prop('disabled',true).text('Saving…');
        $.post(AJ,{action:'jm_crm_save_log',nonce:NK,user_id:uid,call_status:status,
            call_notes:notes,logged_by:by,promise_date:pdate,promise_amount:pamt},function(res){
            $('#mlog-save').prop('disabled',false).text('Save Log');
            if(res.success){closeLog();showToast('✅ Call logged');setTimeout(()=>location.reload(),800);}
            else $('#mlog-err').text('Error: '+(res.data||'Unknown'));
        });
    };

    // ── History modal ─────────────────────────────────────────────────────
    window.openHistory=function(uid,name){
        $('#mhist-cname').text(name);
        $('#mhist-body').html('<div class="crm-spinner">Loading…</div>');
        $('#modal-hist').fadeIn(150);
        $.get(AJ,{action:'jm_crm_get_history',nonce:NK,user_id:uid},function(res){
            if(!res.success||!res.data.length){$('#mhist-body').html('<p class="crm-empty" style="padding:30px">No history found.</p>');return;}
            let h='<div class="crm-log-scroll"><table class="crm-log-tbl"><thead><tr><th>Date/Time</th><th>Status</th><th>Notes</th><th>PTP</th><th>Amt</th><th>By</th></tr></thead><tbody>';
            res.data.forEach(r=>{
                const dt=new Date(r.logged_at.replace(' ','T'));
                const ds=dt.toLocaleDateString('en-IN',{day:'2-digit',month:'short',year:'2-digit'})+' '+dt.toLocaleTimeString('en-IN',{hour:'2-digit',minute:'2-digit'});
                const ptp=r.promise_date?new Date(r.promise_date+'T00:00:00').toLocaleDateString('en-IN',{day:'2-digit',month:'short'}):'—';
                const pa=r.promise_amount>0?'₹'+Number(r.promise_amount).toLocaleString('en-IN'):'—';
                const cl=r.call_status.toLowerCase().replace(/\s+/g,'-');
                h+=`<tr><td>${ds}</td><td><span class="bpill lchip-${cl}">${r.call_status}</span></td><td>${r.call_notes||'—'}</td><td>${ptp}</td><td>${pa}</td><td>${r.logged_by}</td></tr>`;
            });
            $('#mhist-body').html(h+'</tbody></table></div>');
        });
    };
    window.closeHist=function(){$('#modal-hist').fadeOut(150);};

    // Overlay click to close
    $('.crm-overlay').on('click',function(e){if($(e.target).is('.crm-overlay'))$(this).fadeOut(150);});

    // Toast
    window.showToast=function(msg){
        const t=$('<div class="crm-toast">'+msg+'</div>').appendTo('body');
        setTimeout(()=>t.addClass('show'),10);
        setTimeout(()=>{t.removeClass('show');setTimeout(()=>t.remove(),300);},3000);
    };
})(jQuery);
</script>

<?php return ob_get_clean();
}