<?php
declare(strict_types=1);
if (session_status() === PHP_SESSION_NONE) session_start();
require_once __DIR__ . '/../config.php';
if (!isset($_SESSION['user_id'])) {
    http_response_code(401);
    echo json_encode(['success' => false, 'message' => 'Unauthorized']);
    exit;
}

header('Content-Type: application/json');
$conn   = getDBConnection();
$action = trim((string) ($_POST['action'] ?? $_GET['action'] ?? ''));
$userId = (int) $_SESSION['user_id'];
$role   = (string) ($_SESSION['role'] ?? '');

if (!$conn instanceof mysqli) {
    echo json_encode(['success' => false, 'message' => 'Database unavailable']); exit;
}

// Ensure tables exist
$conn->query("CREATE TABLE IF NOT EXISTS announcements (
  id INT AUTO_INCREMENT PRIMARY KEY,
  title VARCHAR(255) NOT NULL,
  body TEXT NOT NULL,
  target_role VARCHAR(50) DEFAULT 'all',
  is_pinned TINYINT(1) NOT NULL DEFAULT 0,
  created_by INT DEFAULT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  KEY idx_created_at (created_at),
  KEY idx_target (target_role)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

$conn->query("CREATE TABLE IF NOT EXISTS internal_messages (
  id INT AUTO_INCREMENT PRIMARY KEY,
  sender_id INT NOT NULL,
  recipient_id INT NOT NULL,
  subject VARCHAR(255) DEFAULT '',
  body TEXT NOT NULL,
  parent_id INT DEFAULT NULL,
  is_read TINYINT(1) NOT NULL DEFAULT 0,
  sent_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  KEY idx_recipient (recipient_id, is_read),
  KEY idx_sender (sender_id),
  KEY idx_thread (parent_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

switch ($action) {

    // ═══════════════════════════════════════════════════════════════════════
    // ANNOUNCEMENTS
    // ═══════════════════════════════════════════════════════════════════════

    case 'get_announcements':
        $filter = trim((string) ($_GET['filter'] ?? 'all'));

        // Only show announcements targeted at 'all' or the current user's role
        $conditions = ["(a.target_role = 'all' OR a.target_role = ?)"];
        if ($filter === 'pinned') $conditions[] = 'a.is_pinned = 1';
        $where = 'WHERE ' . implode(' AND ', $conditions);

        $stmt = $conn->prepare(
            "SELECT a.*, u.full_name AS author_name
             FROM announcements a
             LEFT JOIN users u ON u.id = a.created_by
             {$where}
             ORDER BY a.is_pinned DESC, a.created_at DESC
             LIMIT 100"
        );
        $stmt->bind_param('s', $role);
        $stmt->execute();
        $rows = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
        $stmt->close();
        echo json_encode($rows);
        break;

    case 'save_announcement':
        $can_manage = in_array($role, ['admin','headteacher','director','registrar'], true);
        if (!$can_manage) { echo json_encode(['success' => false, 'message' => 'Insufficient permissions']); break; }

        $id          = (int) ($_POST['id'] ?? 0);
        // Use strip_tags + trim — NOT sanitize() — so no HTML-entity double-encoding in DB.
        // Output escaping is handled by esc() in JavaScript.
        $title       = strip_tags(trim((string) ($_POST['title'] ?? '')));
        $body        = strip_tags(trim((string) ($_POST['body'] ?? '')), '<b><i><strong><em><ul><li><ol><br><p>');
        $target_role = trim((string) ($_POST['target_role'] ?? 'all'));
        $is_pinned   = isset($_POST['is_pinned']) ? 1 : 0;

        if ($title === '' || $body === '') {
            echo json_encode(['success' => false, 'message' => 'Title and body are required']); break;
        }

        $allowed_targets = ['all','admin','teacher','staff','registrar','headteacher','director'];
        if (!in_array($target_role, $allowed_targets, true)) $target_role = 'all';

        if ($id === 0) {
            $stmt = $conn->prepare(
                "INSERT INTO announcements (title, body, target_role, is_pinned, created_by) VALUES (?, ?, ?, ?, ?)"
            );
            $stmt->bind_param('sssii', $title, $body, $target_role, $is_pinned, $userId);
        } else {
            $stmt = $conn->prepare(
                "UPDATE announcements SET title=?, body=?, target_role=?, is_pinned=? WHERE id=?"
            );
            $stmt->bind_param('sssii', $title, $body, $target_role, $is_pinned, $id);
        }
        $stmt->execute();
        $new_id = $id === 0 ? (int) $conn->insert_id : $id;
        $stmt->close();
        echo json_encode(['success' => true, 'id' => $new_id, 'message' => 'Announcement saved']);
        break;

    case 'delete_announcement':
        if (!in_array($role, ['admin','headteacher','director'], true)) {
            echo json_encode(['success' => false, 'message' => 'Insufficient permissions']); break;
        }
        $id = (int) ($_POST['id'] ?? 0);
        $stmt = $conn->prepare("DELETE FROM announcements WHERE id = ?");
        $stmt->bind_param('i', $id);
        $stmt->execute();
        $stmt->close();
        echo json_encode(['success' => true]);
        break;

    case 'toggle_pin':
        if (!in_array($role, ['admin','headteacher','director','registrar'], true)) {
            echo json_encode(['success' => false, 'message' => 'Insufficient permissions']); break;
        }
        $id = (int) ($_POST['id'] ?? 0);
        $stmt = $conn->prepare("UPDATE announcements SET is_pinned = 1 - is_pinned WHERE id = ?");
        $stmt->bind_param('i', $id);
        $stmt->execute();
        $stmt->close();
        $r = $conn->query("SELECT is_pinned FROM announcements WHERE id = {$id} LIMIT 1");
        $pinned = (int) ($r ? $r->fetch_assoc()['is_pinned'] : 0);
        echo json_encode(['success' => true, 'is_pinned' => $pinned]);
        break;

    // ═══════════════════════════════════════════════════════════════════════
    // MESSAGES — INBOX / SENT / COMPOSE / REPLY
    // ═══════════════════════════════════════════════════════════════════════

    case 'get_inbox':
        // Show root-level messages where:
        //   a) I am the recipient (messages sent to me), OR
        //   b) I am the sender AND there are unread replies addressed to me
        // Per-thread unread count is included so the UI can show badges.
        $stmt = $conn->prepare(
            "SELECT m.*,
                    us.full_name AS sender_name,
                    ur.full_name AS recipient_name,
                    COALESCE(
                        (SELECT MAX(r.sent_at) FROM internal_messages r WHERE r.parent_id = m.id),
                        m.sent_at
                    ) AS last_activity,
                    (
                        SELECT COUNT(*) FROM internal_messages r2
                        WHERE (r2.id = m.id OR r2.parent_id = m.id)
                          AND r2.recipient_id = ? AND r2.is_read = 0
                    ) AS unread_count
             FROM internal_messages m
             INNER JOIN users us ON us.id = m.sender_id
             INNER JOIN users ur ON ur.id = m.recipient_id
             WHERE m.parent_id IS NULL
               AND (
                   m.recipient_id = ?
                   OR (
                       m.sender_id = ?
                       AND EXISTS (
                           SELECT 1 FROM internal_messages r3
                           WHERE r3.parent_id = m.id
                             AND r3.recipient_id = ?
                             AND r3.is_read = 0
                       )
                   )
               )
             ORDER BY last_activity DESC
             LIMIT 100"
        );
        $stmt->bind_param('iiii', $userId, $userId, $userId, $userId);
        $stmt->execute();
        $rows = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
        $stmt->close();
        echo json_encode($rows);
        break;

    case 'get_sent':
        $stmt = $conn->prepare(
            "SELECT m.*,
                    ur.full_name AS recipient_name,
                    us.full_name AS sender_name,
                    COALESCE(
                        (SELECT MAX(r.sent_at) FROM internal_messages r WHERE r.parent_id = m.id),
                        m.sent_at
                    ) AS last_activity,
                    (SELECT COUNT(*) FROM internal_messages r2 WHERE r2.parent_id = m.id) AS reply_count
             FROM internal_messages m
             INNER JOIN users ur ON ur.id = m.recipient_id
             INNER JOIN users us ON us.id = m.sender_id
             WHERE m.sender_id = ? AND m.parent_id IS NULL
             ORDER BY last_activity DESC
             LIMIT 100"
        );
        $stmt->bind_param('i', $userId);
        $stmt->execute();
        $rows = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
        $stmt->close();
        echo json_encode($rows);
        break;

    case 'get_thread':
        $root_id = (int) ($_GET['id'] ?? 0);

        // Fetch root message — user must be sender or recipient
        $stmt = $conn->prepare(
            "SELECT m.*, u.full_name AS sender_name, r.full_name AS recipient_name
             FROM internal_messages m
             INNER JOIN users u ON u.id = m.sender_id
             INNER JOIN users r ON r.id = m.recipient_id
             WHERE m.id = ? AND (m.sender_id = ? OR m.recipient_id = ?)
             LIMIT 1"
        );
        $stmt->bind_param('iii', $root_id, $userId, $userId);
        $stmt->execute();
        $root = $stmt->get_result()->fetch_assoc();
        $stmt->close();

        if (!$root) { echo json_encode(['success' => false, 'message' => 'Message not found']); break; }

        // Mark root as read if we're the recipient
        if ((int) $root['recipient_id'] === $userId && !(int) $root['is_read']) {
            $conn->query("UPDATE internal_messages SET is_read = 1 WHERE id = {$root_id}");
        }

        // Fetch replies (both parties can see the thread)
        $stmt2 = $conn->prepare(
            "SELECT m.*, u.full_name AS sender_name, r.full_name AS recipient_name
             FROM internal_messages m
             INNER JOIN users u ON u.id = m.sender_id
             INNER JOIN users r ON r.id = m.recipient_id
             WHERE m.parent_id = ?
             ORDER BY m.sent_at ASC"
        );
        $stmt2->bind_param('i', $root_id);
        $stmt2->execute();
        $replies = $stmt2->get_result()->fetch_all(MYSQLI_ASSOC);
        $stmt2->close();

        // Mark all replies addressed to me as read
        $conn->query(
            "UPDATE internal_messages SET is_read = 1
             WHERE parent_id = {$root_id} AND recipient_id = {$userId}"
        );

        echo json_encode(['success' => true, 'root' => $root, 'replies' => $replies]);
        break;

    case 'send_message':
        $recipient_id = (int) ($_POST['recipient_id'] ?? 0);
        // Store clean text — NOT sanitize() which would HTML-encode before storage
        $subject   = strip_tags(trim((string) ($_POST['subject'] ?? '')));
        $body      = strip_tags(trim((string) ($_POST['body'] ?? '')));
        $parent_id = (int) ($_POST['parent_id'] ?? 0) ?: null;

        if ($recipient_id <= 0) {
            echo json_encode(['success' => false, 'message' => 'Recipient is required']); break;
        }
        if ($body === '') {
            echo json_encode(['success' => false, 'message' => 'Message body is required']); break;
        }
        if ($recipient_id === $userId) {
            echo json_encode(['success' => false, 'message' => 'You cannot send a message to yourself']); break;
        }

        // Verify recipient exists and is active — users table uses is_active column
        $chk = $conn->prepare("SELECT id FROM users WHERE id = ? AND is_active = 1 LIMIT 1");
        $chk->bind_param('i', $recipient_id);
        $chk->execute();
        if (!$chk->get_result()->fetch_assoc()) {
            $chk->close();
            echo json_encode(['success' => false, 'message' => 'Recipient not found or inactive']); break;
        }
        $chk->close();

        $stmt = $conn->prepare(
            "INSERT INTO internal_messages (sender_id, recipient_id, subject, body, parent_id)
             VALUES (?, ?, ?, ?, ?)"
        );
        $stmt->bind_param('iissi', $userId, $recipient_id, $subject, $body, $parent_id);
        $stmt->execute();
        $new_id = (int) $conn->insert_id;
        $stmt->close();
        echo json_encode(['success' => true, 'id' => $new_id, 'message' => 'Message sent']);
        break;

    case 'delete_message':
        // Soft-delete: users can delete threads they own (as sender of root)
        $id = (int) ($_POST['id'] ?? 0);
        // Only the sender of the root message can delete the whole thread
        $stmt = $conn->prepare(
            "DELETE FROM internal_messages WHERE id = ? AND sender_id = ? AND parent_id IS NULL"
        );
        $stmt->bind_param('ii', $id, $userId);
        $stmt->execute();
        $affected = $stmt->affected_rows;
        $stmt->close();
        if ($affected > 0) {
            // Also delete replies
            $conn->query("DELETE FROM internal_messages WHERE parent_id = {$id}");
        }
        echo json_encode(['success' => true, 'deleted' => $affected > 0]);
        break;

    case 'get_unread_count':
        $stmt = $conn->prepare(
            "SELECT COUNT(*) AS cnt FROM internal_messages WHERE recipient_id = ? AND is_read = 0"
        );
        $stmt->bind_param('i', $userId);
        $stmt->execute();
        $cnt = (int) $stmt->get_result()->fetch_assoc()['cnt'];
        $stmt->close();
        echo json_encode(['count' => $cnt]);
        break;

    case 'get_users':
        // Recipient list for compose dropdown — exclude self, show active users only
        $r = $conn->query(
            "SELECT id, full_name AS name, role
             FROM users
             WHERE is_active = 1 AND id != {$userId}
             ORDER BY full_name"
        );
        $users = [];
        if ($r) while ($row = $r->fetch_assoc()) $users[] = $row;
        echo json_encode($users);
        break;

    default:
        echo json_encode(['success' => false, 'message' => 'Unknown action']);
}
