<?php
// includes/discipline_system.php
// Short Mistake / Warning system with role hierarchy:
// Admin -> CSR Managers + Team Leaders + Agents; CSR Manager -> Team Leaders + Agents; Team Leader -> Agents in own team; Agents -> view only.

require_once __DIR__ . '/app_helpers.php';

function disc_h($v): string { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); }

function discEnsureTables(PDO $db): void {
    ensureCsrTeamTables($db);
    addColumnIfMissing($db, 'csr_users', 'role', "ENUM('csr','team_leader','csr_manager') NOT NULL DEFAULT 'csr' AFTER max_active_chats");

    $db->exec("CREATE TABLE IF NOT EXISTS csr_discipline_records (
        id INT AUTO_INCREMENT PRIMARY KEY,
        record_type ENUM('mistake','warning') NOT NULL,
        sender_id INT NOT NULL,
        sender_role VARCHAR(40) NOT NULL DEFAULT 'csr',
        recipient_id INT NOT NULL,
        recipient_role VARCHAR(40) NOT NULL DEFAULT 'csr',
        team_id INT NULL,
        title VARCHAR(180) NOT NULL,
        message TEXT NOT NULL,
        severity ENUM('low','normal','high') NOT NULL DEFAULT 'normal',
        is_read TINYINT(1) NOT NULL DEFAULT 0,
        read_at DATETIME NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        INDEX idx_disc_type_created (record_type, created_at),
        INDEX idx_disc_sender (sender_id, record_type),
        INDEX idx_disc_recipient (recipient_id, record_type, is_read),
        INDEX idx_disc_team (team_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
}

function discUser(PDO $db, int $id): ?array {
    $stmt = $db->prepare("SELECT id, first_name, last_name, email, COALESCE(role,'csr') AS role, is_active FROM csr_users WHERE id=:id LIMIT 1");
    $stmt->execute([':id'=>$id]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    return $row ?: null;
}

function discName(array $u): string {
    $name = trim(($u['first_name'] ?? '') . ' ' . ($u['last_name'] ?? ''));
    return $name ?: (($u['email'] ?? '') ?: ('User #' . (int)($u['id'] ?? 0)));
}

function discRoleLabel(?string $role): string {
    return match($role) { 'admin' => 'Admin', 'csr_manager' => 'CSR Manager', 'team_leader' => 'Team Leader', default => 'Agent' };
}

function discCanSend(string $senderRole, string $recordType): bool {
    return in_array($senderRole, ['admin','csr_manager','team_leader'], true) && in_array($recordType, ['mistake','warning'], true);
}

function discAllowedRecipients(PDO $db, int $senderId, string $senderRole): array {
    discEnsureTables($db);
    if ($senderRole === 'admin') {
        $sql = "SELECT DISTINCT cu.id, cu.first_name, cu.last_name, cu.email, COALESCE(cu.role,'csr') AS role,
                       ct.id AS team_id, ct.team_name
                FROM csr_users cu
                LEFT JOIN csr_team_members tm ON tm.csr_id = cu.id
                LEFT JOIN csr_teams ct ON ct.id = tm.team_id AND ct.is_active = 1
                WHERE cu.is_active = 1
                  AND COALESCE(cu.role,'csr') IN ('csr_manager','team_leader','csr')
                ORDER BY FIELD(COALESCE(cu.role,'csr'),'csr_manager','team_leader','csr'), ct.team_name, cu.first_name, cu.last_name";
        $stmt = $db->prepare($sql);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
    }
    if ($senderRole === 'csr_manager') {
        $sql = "SELECT DISTINCT cu.id, cu.first_name, cu.last_name, cu.email, COALESCE(cu.role,'csr') AS role,
                       ct.id AS team_id, ct.team_name
                FROM csr_users cu
                LEFT JOIN csr_team_members tm ON tm.csr_id = cu.id
                LEFT JOIN csr_teams ct ON ct.id = tm.team_id AND ct.is_active = 1
                WHERE cu.is_active = 1
                  AND cu.id <> :sender
                  AND COALESCE(cu.role,'csr') IN ('team_leader','csr')
                ORDER BY FIELD(COALESCE(cu.role,'csr'),'team_leader','csr'), ct.team_name, cu.first_name, cu.last_name";
        $stmt = $db->prepare($sql);
        $stmt->execute([':sender'=>$senderId]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
    }
    if ($senderRole === 'team_leader') {
        $sql = "SELECT DISTINCT cu.id, cu.first_name, cu.last_name, cu.email, COALESCE(cu.role,'csr') AS role,
                       ct.id AS team_id, ct.team_name
                FROM csr_teams ct
                JOIN csr_team_members tm ON tm.team_id = ct.id
                JOIN csr_users cu ON cu.id = tm.csr_id
                WHERE ct.is_active = 1
                  AND ct.manager_id = :sender
                  AND cu.is_active = 1
                  AND COALESCE(cu.role,'csr') = 'csr'
                ORDER BY ct.team_name, cu.first_name, cu.last_name";
        $stmt = $db->prepare($sql);
        $stmt->execute([':sender'=>$senderId]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
    }
    return [];
}

function discRecipientIsAllowed(PDO $db, int $senderId, string $senderRole, int $recipientId): ?array {
    foreach (discAllowedRecipients($db, $senderId, $senderRole) as $u) {
        if ((int)$u['id'] === $recipientId) return $u;
    }
    return null;
}

function discNotify(PDO $db, int $recipientId, string $recordType, string $title, string $message, int $recordId, string $recipientRole): void {
    try {
        $link = ($recipientRole === 'team_leader') ? $recordType . '.php' : $recordType . '.php';
        $type = $recordType === 'warning' ? 'warning' : 'danger';
        $display = ucfirst($recordType);
        $stmt = $db->prepare("INSERT INTO csr_notifications (csr_id, title, message, type, link, reference_id, reference_type, created_at)
                              VALUES (:csr_id, :title, :message, :type, :link, :reference_id, 'discipline', NOW())");
        $stmt->execute([
            ':csr_id'=>$recipientId,
            ':title'=>$display . ': ' . $title,
            ':message'=>mb_substr($message, 0, 250),
            ':type'=>$type,
            ':link'=>$link,
            ':reference_id'=>$recordId,
        ]);
    } catch (Throwable $e) {
        // Notifications are helpful but should not block saving the record.
    }
}

function discCreate(PDO $db, int $senderId, string $senderRole, string $recordType, int $recipientId, string $title, string $message, string $severity='normal'): int {
    discEnsureTables($db);
    if (!discCanSend($senderRole, $recordType)) throw new Exception('You are not allowed to send this.');
    $recipient = discRecipientIsAllowed($db, $senderId, $senderRole, $recipientId);
    if (!$recipient) throw new Exception('Selected person is not allowed for your role.');

    $title = trim($title);
    $message = trim($message);
    if ($title === '') $title = ucfirst($recordType);
    if ($message === '') throw new Exception('Please add details.');
    if (!in_array($severity, ['low','normal','high'], true)) $severity = 'normal';

    $stmt = $db->prepare("INSERT INTO csr_discipline_records
        (record_type, sender_id, sender_role, recipient_id, recipient_role, team_id, title, message, severity, created_at)
        VALUES (:record_type, :sender_id, :sender_role, :recipient_id, :recipient_role, :team_id, :title, :message, :severity, NOW())");
    $stmt->execute([
        ':record_type'=>$recordType,
        ':sender_id'=>$senderId,
        ':sender_role'=>$senderRole,
        ':recipient_id'=>$recipientId,
        ':recipient_role'=>$recipient['role'] ?? 'csr',
        ':team_id'=>!empty($recipient['team_id']) ? (int)$recipient['team_id'] : null,
        ':title'=>$title,
        ':message'=>$message,
        ':severity'=>$severity,
    ]);
    $id = (int)$db->lastInsertId();
    discNotify($db, $recipientId, $recordType, $title, $message, $id, $recipient['role'] ?? 'csr');
    return $id;
}

function discListSent(PDO $db, int $senderId, string $recordType, int $limit=150): array {
    discEnsureTables($db);
    $stmt = $db->prepare("SELECT dr.*, CONCAT(r.first_name,' ',r.last_name) AS recipient_name, r.email AS recipient_email,
                                 COALESCE(r.role,'csr') AS live_recipient_role, ct.team_name
                          FROM csr_discipline_records dr
                          JOIN csr_users r ON r.id = dr.recipient_id
                          LEFT JOIN csr_teams ct ON ct.id = dr.team_id
                          WHERE dr.sender_id = :sender_id AND dr.record_type = :record_type
                          ORDER BY dr.created_at DESC LIMIT " . (int)$limit);
    $stmt->execute([':sender_id'=>$senderId, ':record_type'=>$recordType]);
    return $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
}


function discListSentByRole(PDO $db, int $senderId, string $senderRole, string $recordType, int $limit=150): array {
    discEnsureTables($db);
    $stmt = $db->prepare("SELECT dr.*, CONCAT(r.first_name,' ',r.last_name) AS recipient_name, r.email AS recipient_email,
                                 COALESCE(r.role,'csr') AS live_recipient_role, ct.team_name
                          FROM csr_discipline_records dr
                          JOIN csr_users r ON r.id = dr.recipient_id
                          LEFT JOIN csr_teams ct ON ct.id = dr.team_id
                          WHERE dr.sender_id = :sender_id AND dr.sender_role = :sender_role AND dr.record_type = :record_type
                          ORDER BY dr.created_at DESC LIMIT " . (int)$limit);
    $stmt->execute([':sender_id'=>$senderId, ':sender_role'=>$senderRole, ':record_type'=>$recordType]);
    return $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
}

function discListReceived(PDO $db, int $recipientId, string $recordType, int $limit=150): array {
    discEnsureTables($db);
    $stmt = $db->prepare("SELECT dr.*,
                                 CASE WHEN dr.sender_role = 'admin'
                                      THEN TRIM(CONCAT(COALESCE(au.first_name,''),' ',COALESCE(au.last_name,'')))
                                      ELSE TRIM(CONCAT(COALESCE(s.first_name,''),' ',COALESCE(s.last_name,'')))
                                 END AS sender_name,
                                 CASE WHEN dr.sender_role = 'admin' THEN au.email ELSE s.email END AS sender_email,
                                 CASE WHEN dr.sender_role = 'admin' THEN 'admin' ELSE COALESCE(s.role,'csr') END AS live_sender_role,
                                 ct.team_name
                          FROM csr_discipline_records dr
                          LEFT JOIN csr_users s ON s.id = dr.sender_id AND dr.sender_role <> 'admin'
                          LEFT JOIN admin_users au ON au.id = dr.sender_id AND dr.sender_role = 'admin'
                          LEFT JOIN csr_teams ct ON ct.id = dr.team_id
                          WHERE dr.recipient_id = :recipient_id AND dr.record_type = :record_type
                          ORDER BY dr.created_at DESC LIMIT " . (int)$limit);
    $stmt->execute([':recipient_id'=>$recipientId, ':record_type'=>$recordType]);
    return $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
}

function discMarkRead(PDO $db, int $recordId, int $recipientId): void {
    discEnsureTables($db);
    $stmt = $db->prepare("UPDATE csr_discipline_records SET is_read=1, read_at=NOW() WHERE id=:id AND recipient_id=:recipient_id");
    $stmt->execute([':id'=>$recordId, ':recipient_id'=>$recipientId]);
}

function discPageTitle(string $type): string { return $type === 'warning' ? 'Warning' : 'Mistake'; }
function discIcon(string $type): string { return $type === 'warning' ? 'fas fa-triangle-exclamation' : 'fas fa-circle-exclamation'; }
function discColor(string $type): string { return $type === 'warning' ? 'var(--cm-yellow)' : 'var(--cm-red)'; }
?>
