<?php
header('Content-Type: application/json');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
require_once 'auth/session.php';
require_once 'includes/opengraph.php';
require_once 'includes/ai_filtering.php';
require_once 'includes/permissions.php';

// Check for Bot token in headers
$headers = getallheaders();
$bot_token = null;
if (isset($headers['Authorization']) && preg_match('/Bot\s+(\S+)/', $headers['Authorization'], $matches)) {
    $bot_token = $matches[1];
}

$user_id = null;
if ($bot_token) {
    $stmt = db()->prepare("SELECT id FROM users WHERE bot_token = ? AND is_bot = TRUE");
    $stmt->execute([$bot_token]);
    $bot = $stmt->fetch();
    if ($bot) {
        $user_id = $bot['id'];
    } else {
        http_response_code(401);
        echo json_encode(['success' => false, 'error' => 'Invalid Bot Token']);
        exit;
    }
} elseif (isset($_SESSION['user_id'])) {
    $user_id = $_SESSION['user_id'];
} else {
    http_response_code(401);
    echo json_encode(['success' => false, 'error' => 'Unauthorized']);
    exit;
}

if ($_SERVER['REQUEST_METHOD'] === 'GET') {
    $channel_id = $_GET['channel_id'] ?? 0;
    $pinned = isset($_GET['pinned']) && $_GET['pinned'] == 1;

    if ($pinned) {
        try {
            $thread_id = isset($_GET['thread_id']) && $_GET['thread_id'] !== '' ? (int)$_GET['thread_id'] : null;

            // Get server_id for the channel
            $stmt = db()->prepare("SELECT server_id FROM channels WHERE id = ?");
            $stmt->execute([$channel_id]);
            $server_id = $stmt->fetchColumn();

            $query = "
                SELECT m.*, u.display_name as username, u.username as login_name, u.avatar_url,
                (SELECT r.color FROM roles r JOIN user_roles ur ON r.id = ur.role_id WHERE ur.user_id = u.id AND r.server_id = ? ORDER BY r.position DESC LIMIT 1) as role_color,
                (SELECT r.icon_url FROM roles r JOIN user_roles ur ON r.id = ur.role_id WHERE ur.user_id = u.id AND r.server_id = ? ORDER BY r.position DESC LIMIT 1) as role_icon,
                (SELECT GROUP_CONCAT(CONCAT(sb.name, '|', sb.image_url) SEPARATOR ':::') FROM member_badges mb JOIN server_badges sb ON mb.badge_id = sb.id WHERE mb.user_id = u.id AND mb.server_id = ?) as badge_data
                FROM messages m 
                JOIN users u ON m.user_id = u.id 
                WHERE m.channel_id = ? AND m.is_pinned = 1
            ";
            $params = [$server_id ?: 0, $server_id ?: 0, $server_id ?: 0, $channel_id];

            if ($thread_id !== null) {
                $query .= " AND m.thread_id = ?";
                $params[] = $thread_id;
            } else {
                $query .= " AND m.thread_id IS NULL";
            }

            $query .= " ORDER BY m.created_at DESC";

            $stmt = db()->prepare($query);
            $stmt->execute($params);
            $msgs = $stmt->fetchAll();
            
            foreach ($msgs as &$m) {
                $m['time'] = date('H:i', strtotime($m['created_at']));
                $m['metadata'] = $m['metadata'] ? json_decode($m['metadata']) : null;
            }
            
            echo json_encode(['success' => true, 'messages' => $msgs]);
        } catch (Exception $e) {
            echo json_encode(['success' => false, 'error' => $e->getMessage()]);
        }
        exit;
    }

    if (isset($_GET['after_id'])) {
        try {
            $after_id = (int)$_GET['after_id'];
            $thread_id = isset($_GET['thread_id']) && $_GET['thread_id'] !== '' ? (int)$_GET['thread_id'] : null;

            // Get server_id for the channel
            $stmt = db()->prepare("SELECT server_id FROM channels WHERE id = ?");
            $stmt->execute([$channel_id]);
            $server_id = $stmt->fetchColumn();

            $query = "
                SELECT m.*, u.display_name as username, u.username as login_name, u.avatar_url,
                (SELECT r.color FROM roles r JOIN user_roles ur ON r.id = ur.role_id WHERE ur.user_id = u.id AND r.server_id = ? ORDER BY r.position DESC LIMIT 1) as role_color,
                (SELECT r.icon_url FROM roles r JOIN user_roles ur ON r.id = ur.role_id WHERE ur.user_id = u.id AND r.server_id = ? ORDER BY r.position DESC LIMIT 1) as role_icon,
                (SELECT GROUP_CONCAT(CONCAT(sb.name, '|', sb.image_url) SEPARATOR ':::') FROM member_badges mb JOIN server_badges sb ON mb.badge_id = sb.id WHERE mb.user_id = u.id AND mb.server_id = ?) as badge_data
                FROM messages m 
                JOIN users u ON m.user_id = u.id 
                WHERE m.channel_id = ? AND m.id > ?
            ";
            $params = [$server_id ?: 0, $server_id ?: 0, $server_id ?: 0, $channel_id, $after_id];

            if ($thread_id !== null) {
                $query .= " AND m.thread_id = ?";
                $params[] = $thread_id;
            } else {
                $query .= " AND m.thread_id IS NULL";
            }

            $query .= " ORDER BY m.id ASC";

            $stmt = db()->prepare($query);
            $stmt->execute($params);
            $msgs = $stmt->fetchAll();
            
            foreach ($msgs as &$m) {
                $m['time'] = date('H:i', strtotime($m['created_at']));
                $m['metadata'] = $m['metadata'] ? json_decode($m['metadata']) : null;
            }
            
            echo json_encode(['success' => true, 'messages' => $msgs]);
        } catch (Exception $e) {
            echo json_encode(['success' => false, 'error' => $e->getMessage()]);
        }
        exit;
    }
}

if ($_SERVER['REQUEST_METHOD'] === 'PUT') {
    $data = json_decode(file_get_contents('php://input'), true);
    $message_id = $data['id'] ?? 0;
    $content = $data['content'] ?? '';
    $action = $data['action'] ?? 'edit';

    try {
        $stmt = db()->prepare("SELECT user_id, channel_id FROM messages WHERE id = ?");
        $stmt->execute([$message_id]);
        $msg_data = $stmt->fetch();
        
        if (!$msg_data) {
            echo json_encode(['success' => false, 'error' => 'Message not found']);
            exit;
        }

        if ($action === 'pin') {
            if (!Permissions::canDoInChannel($user_id, $msg_data['channel_id'], Permissions::MANAGE_MESSAGES)) {
                echo json_encode(['success' => false, 'error' => 'Unauthorized']);
                exit;
            }
            $stmt = db()->prepare("UPDATE messages SET is_pinned = 1 WHERE id = ?");
            $stmt->execute([$message_id]);
            echo json_encode(['success' => true]);
            exit;
        }
        if ($action === 'unpin') {
            if (!Permissions::canDoInChannel($user_id, $msg_data['channel_id'], Permissions::MANAGE_MESSAGES)) {
                echo json_encode(['success' => false, 'error' => 'Unauthorized']);
                exit;
            }
            $stmt = db()->prepare("UPDATE messages SET is_pinned = 0 WHERE id = ?");
            $stmt->execute([$message_id]);
            echo json_encode(['success' => true]);
            exit;
        }

        if ($msg_data['user_id'] != $user_id && !Permissions::canDoInChannel($user_id, $msg_data['channel_id'], Permissions::MANAGE_MESSAGES)) {
            echo json_encode(['success' => false, 'error' => 'Unauthorized']);
            exit;
        }

        if (empty($content)) {
            echo json_encode(['success' => false, 'error' => 'Content cannot be empty']);
            exit;
        }

        $metadata = null;
        if (isset($data['is_announcement']) && $data['is_announcement'] == '1') {
            if (!Permissions::canDoInChannel($user_id, $msg_data['channel_id'], Permissions::CREATE_ANNOUNCEMENT)) {
                echo json_encode(['success' => false, 'error' => 'You do not have permission to manage announcements in this channel.']);
                exit;
            }
            $metadata = json_encode([
                'is_manual_announcement' => true,
                'title' => $data['ann_title'] ?? '',
                'color' => $data['ann_color'] ?? '#3c6f7c',
                'description' => $content,
                'url' => $data['ann_link'] ?? ''
            ]);
        } elseif (isset($data['is_poll']) && $data['is_poll'] == '1') {
            // Check permissions
            if ($msg_data['user_id'] != $user_id && !Permissions::canDoInChannel($user_id, $msg_data['channel_id'], Permissions::MANAGE_MESSAGES)) {
                echo json_encode(['success' => false, 'error' => 'Unauthorized']);
                exit;
            }

            $options = $data['poll_options'] ?? [];
            $emotes = $data['poll_emotes'] ?? [];
            
            $stmt_old = db()->prepare("SELECT metadata, created_at FROM messages WHERE id = ?");
            $stmt_old->execute([$message_id]);
            $msg_info = $stmt_old->fetch();
            $old_meta = json_decode($msg_info['metadata'] ?? '{}', true);
            
            // Recalculate end date if duration provided, otherwise keep old
            $end_date = $old_meta['poll_end_date'] ?? date('Y-m-d H:i:s', time() + 86400);
            if (isset($data['poll_duration'])) {
                $duration = (int)$data['poll_duration'];
                $end_date = date('Y-m-d H:i:s', strtotime($msg_info['created_at']) + $duration);
            }

            $metadata = json_encode([
                'is_poll' => true,
                'poll_title' => $data['poll_title'] ?? 'Sondage',
                'poll_options' => $options,
                'poll_emotes' => $emotes,
                'poll_choice_type' => ($data['allow_multiple'] ?? '0') == '1' ? 'multiple' : 'single',
                'is_anonymous' => ($data['is_anonymous'] ?? '0') == '1',
                'poll_end_date' => $end_date,
                'poll_color' => $data['poll_color'] ?? '#3c6f7c'
            ]);
        }

        if ($metadata) {
            $stmt = db()->prepare("UPDATE messages SET content = ?, metadata = ? WHERE id = ?");
            $stmt->execute([$content, $metadata, $message_id]);
        } else {
            $stmt = db()->prepare("UPDATE messages SET content = ? WHERE id = ?");
            $stmt->execute([$content, $message_id]);
        }
        
        echo json_encode(['success' => true]);
    } catch (Exception $e) {
        echo json_encode(['success' => false, 'error' => $e->getMessage()]);
    }
    exit;
}

if ($_SERVER['REQUEST_METHOD'] === 'DELETE') {
    $data = json_decode(file_get_contents('php://input'), true);
    $message_id = $data['id'] ?? 0;

    try {
        $stmt = db()->prepare("SELECT user_id, channel_id FROM messages WHERE id = ?");
        $stmt->execute([$message_id]);
        $msg_data = $stmt->fetch();
        
        if (!$msg_data) {
            echo json_encode(['success' => false, 'error' => 'Message not found']);
            exit;
        }

        if ($msg_data['user_id'] != $user_id && !Permissions::canDoInChannel($user_id, $msg_data['channel_id'], Permissions::MANAGE_MESSAGES)) {
            echo json_encode(['success' => false, 'error' => 'Unauthorized']);
            exit;
        }

        $stmt = db()->prepare("DELETE FROM messages WHERE id = ?");
        $stmt->execute([$message_id]);
        
        echo json_encode(['success' => true]);
    } catch (Exception $e) {
        echo json_encode(['success' => false, 'error' => $e->getMessage()]);
    }
    exit;
}

$content = '';

$channel_id = 0;
$thread_id = null;
$attachment_url = null;

if (strpos($_SERVER['CONTENT_TYPE'] ?? '', 'application/json') !== false) {
    $data = json_decode(file_get_contents('php://input'), true);
    $content = $data['content'] ?? '';
    $channel_id = $data['channel_id'] ?? 0;
    $thread_id = !empty($data['thread_id']) ? (int)$data['thread_id'] : null;
} else {
    $content = $_POST['content'] ?? '';
    $channel_id = $_POST['channel_id'] ?? 0;
    $thread_id = !empty($_POST['thread_id']) ? (int)$_POST['thread_id'] : null;
    
    // Check if file sharing is allowed in this channel
    $stmt = db()->prepare("SELECT allow_file_sharing FROM channels WHERE id = ?");
    $stmt->execute([$channel_id]);
    $channel = $stmt->fetch();
    $can_share_files = $channel ? (bool)$channel['allow_file_sharing'] : true;

    if (isset($_FILES['file']) && $_FILES['file']['error'] === UPLOAD_ERR_OK) {
        if (!$can_share_files) {
            echo json_encode(['success' => false, 'error' => 'File sharing is disabled in this channel.']);
            exit;
        }
        $upload_dir = 'assets/uploads/';
        if (!is_dir($upload_dir)) mkdir($upload_dir, 0775, true);
        
        $filename = time() . '_' . basename($_FILES['file']['name']);
        $target_file = $upload_dir . $filename;
        
        if (move_uploaded_file($_FILES['file']['tmp_name'], $target_file)) {
            $attachment_url = $target_file;
        }
    }
}

if (empty($content) && empty($attachment_url)) {
    echo json_encode(['success' => false, 'error' => 'Empty content and no attachment']);
    exit;
}

// Check granular permissions
// Check if AI moderation is enabled for this channel
$stmtMod = db()->prepare("SELECT ai_moderation_enabled FROM channels WHERE id = ?");
$stmtMod->execute([$channel_id]);
$channelMod = $stmtMod->fetch();
$ai_moderation_enabled = $channelMod ? (bool)$channelMod["ai_moderation_enabled"] : true;
$can_send = Permissions::canSendInChannel($user_id, $channel_id);
if ($thread_id) {
    // For threads, we check the specific thread permission instead of the general channel permission
    $can_send = Permissions::canDoInChannel($user_id, $channel_id, Permissions::SEND_MESSAGES_IN_THREADS);
}

if (!$can_send) {
    echo json_encode(['success' => false, 'error' => 'You do not have permission to send messages in this channel.']);
    exit;
}

// Check if thread is locked
if ($thread_id) {
    $stmtThread = db()->prepare("SELECT is_locked, channel_id, server_id FROM forum_threads t JOIN channels c ON t.channel_id = c.id WHERE t.id = ?");
    $stmtThread->execute([$thread_id]);
    $threadData = $stmtThread->fetch();
    if ($threadData && $threadData['is_locked']) {
        // Strict lock: no one can post, not even admins. Admins must unlock first.
        echo json_encode(['success' => false, 'error' => 'This thread is locked. Messages are disabled.']);
        exit;
    }
}

if (!empty($content) && $ai_moderation_enabled) {
    $moderation = moderateContent($content);
    if (!$moderation['is_safe']) {
        echo json_encode(['success' => false, 'error' => 'Message flagged as inappropriate: ' . ($moderation['reason'] ?? 'Violation of community standards')]);
        exit;
    }
}

$metadata = null;
if (isset($_POST['is_announcement']) && $_POST['is_announcement'] == '1') {
    if (!Permissions::canDoInChannel($user_id, $channel_id, Permissions::CREATE_ANNOUNCEMENT)) {
        echo json_encode(['success' => false, 'error' => 'You do not have permission to create announcements in this channel.']);
        exit;
    }
    $metadata = json_encode([
        'is_manual_announcement' => true,
        'title' => $_POST['ann_title'] ?? '',
        'color' => $_POST['ann_color'] ?? '#3c6f7c',
        'description' => $content,
        'url' => $_POST['ann_link'] ?? ''
    ]);
    // Clear content for the message text itself if we want it only in the embed
    // But keeping it in content might be good for search/fallback
} elseif (isset($_POST['is_poll']) && $_POST['is_poll'] == '1') {
    if (!Permissions::canDoInChannel($user_id, $channel_id, Permissions::CREATE_POLL)) {
        echo json_encode(['success' => false, 'error' => 'You do not have permission to create polls in this channel.']);
        exit;
    }
    
    $options = json_decode($_POST['poll_options'] ?? '[]', true);
    $emotes = json_decode($_POST['poll_emotes'] ?? '[]', true);
    $duration = (int)($_POST['poll_duration'] ?? 86400);
    $end_date = date('Y-m-d H:i:s', time() + $duration);

    $metadata = json_encode([
        'is_poll' => true,
        'poll_title' => $_POST['poll_title'] ?? 'Sondage',
        'poll_options' => $options,
        'poll_emotes' => $emotes,
        'poll_choice_type' => ($_POST['allow_multiple'] ?? '0') == '1' ? 'multiple' : 'single',
        'is_anonymous' => ($_POST['is_anonymous'] ?? '0') == '1',
        'poll_end_date' => $end_date,
        'poll_color' => $_POST['poll_color'] ?? '#3c6f7c'
    ]);
} elseif (!empty($content) && $ai_moderation_enabled) {
    $urls = extractUrls($content);
    if (!empty($urls)) {
        // Fetch OG data for the first URL
        $ogData = fetchOpenGraphData($urls[0]);
        if ($ogData) {
            $metadata = json_encode($ogData);
        }
    }
}

try {
    $stmt = db()->prepare("INSERT INTO messages (channel_id, thread_id, user_id, content, attachment_url, metadata) VALUES (?, ?, ?, ?, ?, ?)");
    $stmt->execute([$channel_id, $thread_id, $user_id, $content, $attachment_url, $metadata]);
    $last_id = db()->lastInsertId();

    // Update last activity for forum threads
    if ($thread_id) {
        $stmtActivity = db()->prepare("UPDATE forum_threads SET last_activity_at = CURRENT_TIMESTAMP WHERE id = ?");
        $stmtActivity->execute([$thread_id]);
    }

    // Enforce message limit if set
    enforceChannelLimit($channel_id);

    // Get server_id for the channel
    $stmt = db()->prepare("SELECT server_id FROM channels WHERE id = ?");
    $stmt->execute([$channel_id]);
    $server_id = $stmt->fetchColumn();

    // Fetch message with username and role color for the response
    $stmt = db()->prepare("
        SELECT m.*, u.display_name as username, u.username as login_name, u.avatar_url,
        (SELECT r.color FROM roles r JOIN user_roles ur ON r.id = ur.role_id WHERE ur.user_id = u.id AND r.server_id = ? ORDER BY r.position DESC LIMIT 1) as role_color,
                (SELECT r.icon_url FROM roles r JOIN user_roles ur ON r.id = ur.role_id WHERE ur.user_id = u.id AND r.server_id = ? ORDER BY r.position DESC LIMIT 1) as role_icon,
        (SELECT GROUP_CONCAT(CONCAT(sb.name, '|', sb.image_url) SEPARATOR ':::') FROM member_badges mb JOIN server_badges sb ON mb.badge_id = sb.id WHERE mb.user_id = u.id AND mb.server_id = ?) as badge_data
        FROM messages m 
        JOIN users u ON m.user_id = u.id 
        WHERE m.id = ?
    ");
    $stmt->execute([$server_id ?: 0, $server_id ?: 0, $server_id ?: 0, $last_id]);
    $msg = $stmt->fetch();

    echo json_encode([
        'success' => true,
        'message' => [
            'id' => $msg['id'],
            'user_id' => $msg['user_id'],
            'username' => $msg['username'], 'login_name' => $msg['login_name'],
            'avatar_url' => $msg['avatar_url'],
            'role_color' => $msg['role_color'],
            'role_icon' => $msg['role_icon'],
            'badge_data' => $msg['badge_data'],
            'content' => $msg['content'],
            'attachment_url' => $msg['attachment_url'],
            'metadata' => $msg['metadata'] ? json_decode($msg['metadata']) : null,
            'time' => date('H:i', strtotime($msg['created_at']))
        ]
    ]);
} catch (Exception $e) {
    echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
