<?php

namespace App\Controllers;

use App\Core\Controller;
use App\Config\Database;
use App\Middleware\AdminMiddleware;
use App\Services\OneSignalService;
use PDO;

class AdminController extends Controller {
    private $db;
    private $oneSignal;

    public function __construct() {
        $this->db = Database::getInstance()->getConnection();
        $this->oneSignal = new OneSignalService();
    }

    public function getUsers() {
        AdminMiddleware::authenticate();
        $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 50;
        $offset = isset($_GET['offset']) ? (int)$_GET['offset'] : 0;
        $search = isset($_GET['search']) ? $_GET['search'] : '';
        $filter = isset($_GET['filter']) ? $_GET['filter'] : 'all';

        $sql = "SELECT u.* FROM users u WHERE 1=1";
        $params = [];

        if ($search) {
            $sql .= " AND (u.username LIKE ? OR u.email LIKE ? OR u.display_name LIKE ?)";
            $params[] = "%$search%";
            $params[] = "%$search%";
            $params[] = "%$search%";
        }

        if ($filter === 'banned') {
            $sql .= " AND u.is_banned = 1";
        } elseif ($filter === 'bot') {
            $sql .= " AND u.is_seed = 1";
        } elseif ($filter === 'plus') {
            $sql .= " AND u.is_plus_subscriber = 1";
        } elseif ($filter === 'premium_all' || $filter === 'premium') {
            $sql .= " AND (u.is_plus_subscriber = 1 OR (u.boosted_until IS NOT NULL AND u.boosted_until > NOW()))";
        } elseif ($filter === 'boosted') {
            $sql .= " AND u.boosted_until IS NOT NULL AND u.boosted_until > NOW()";
        }

        $sql .= " ORDER BY u.created_at DESC LIMIT ? OFFSET ?";
        
        $stmt = $this->db->prepare($sql);
        foreach ($params as $k => $v) {
            $stmt->bindValue($k + 1, $v);
        }
        $stmt->bindValue(count($params) + 1, $limit, PDO::PARAM_INT);
        $stmt->bindValue(count($params) + 2, $offset, PDO::PARAM_INT);
        $stmt->execute();
        
        $this->json($stmt->fetchAll());
    }

    public function getUserDetails($id) {
        AdminMiddleware::authenticate();
        
        $stmt = $this->db->prepare("SELECT u.* FROM users u WHERE u.id = ?");
        $stmt->execute([$id]);
        $user = $stmt->fetch();
        
        if (!$user) $this->json(['error' => 'User not found'], 404);

        // Stats
        $stats = [];
        $stmt = $this->db->prepare("SELECT COUNT(*) FROM conversations WHERE user_a_id = ? OR user_b_id = ?");
        $stmt->execute([$id, $id]);
        $stats['conversations'] = $stmt->fetchColumn();

        $stmt = $this->db->prepare("SELECT COUNT(*) FROM messages WHERE sender_id = ?");
        $stmt->execute([$id]);
        $stats['messages_sent'] = $stmt->fetchColumn();

        $stmt = $this->db->prepare("SELECT COUNT(*) FROM reports WHERE reported_user_id = ?");
        $stmt->execute([$id]);
        $stats['reports_received'] = $stmt->fetchColumn();

        // Get Alias History (New Feature)
        $stmt = $this->db->prepare("SELECT DISTINCT sender_alias FROM messages WHERE sender_id = ? AND is_anonymous = 1 LIMIT 10");
        $stmt->execute([$id]);
        $user['aliases'] = $stmt->fetchAll(PDO::FETCH_COLUMN);

        $user['stats'] = $stats;
        $this->json($user);
    }

    public function deleteUser($id) {
        $admin = AdminMiddleware::authenticate();
        
        // Soft delete or hard delete? Hard delete for now as per "Delete Account" usually implies
        // But we have FKs.
        // Let's rely on CASCADE for conversations/messages if configured, or delete manually.
        // Schema has ON DELETE CASCADE for most things.
        
        $stmt = $this->db->prepare("DELETE FROM users WHERE id = ?");
        $stmt->execute([$id]);
        
        $this->logAudit($admin['id'], 'delete_user', 'users', $id);
        $this->json(['success' => true]);
    }

    public function getAllConversations() {
        AdminMiddleware::authenticate();
        $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 50;
        $offset = isset($_GET['offset']) ? (int)$_GET['offset'] : 0;
        
        $stmt = $this->db->prepare("
            SELECT 
                c.id,
                c.user_a_id,
                c.user_b_id,
                c.created_at,
                c.updated_at,
                c.last_message_at,
                c.last_message_id,
                c.is_anonymous,
                c.anonymous_alias,
                c.anonymous_participant_id,
                ua.username as sender_real_name,
                ua.avatar_url as sender_avatar_url,
                ua.is_seed as sender_is_bot,
                ub.username as receiver_real_name,
                ub.avatar_url as receiver_avatar_url,
                ub.is_seed as receiver_is_bot,
                m.body_text as last_message_text,
                m.sender_alias as last_msg_alias,
                m.is_anonymous as last_msg_is_anon
            FROM conversations c
            JOIN users ua ON c.user_a_id = ua.id
            JOIN users ub ON c.user_b_id = ub.id
            LEFT JOIN messages m ON c.last_message_id = m.id
            ORDER BY c.last_message_at DESC
            LIMIT ? OFFSET ?
        ");
        $stmt->bindValue(1, $limit, PDO::PARAM_INT);
        $stmt->bindValue(2, $offset, PDO::PARAM_INT);
        $stmt->execute();

        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        foreach ($rows as &$row) {
            $row['is_anonymous'] = ((int)($row['is_anonymous'] ?? 0) === 1);
            $row['last_msg_is_anon'] = ((int)($row['last_msg_is_anon'] ?? 0) === 1);

            $row['display_alias'] = $row['is_anonymous'] ? ($row['anonymous_alias'] ?? null) : null;

            $row['user_a_name'] = $row['sender_real_name'];
            $row['user_a_avatar'] = $row['sender_avatar_url'];
            $row['user_a_is_bot'] = $row['sender_is_bot'];
            $row['user_a_real_name'] = $row['sender_real_name'];

            $row['user_b_name'] = $row['receiver_real_name'];
            $row['user_b_avatar'] = $row['receiver_avatar_url'];
            $row['user_b_is_bot'] = $row['receiver_is_bot'];
            $row['user_b_real_name'] = $row['receiver_real_name'];
        }
        unset($row);

        $this->json($rows);
    }

    public function getUserConversations($userId) {
        AdminMiddleware::authenticate();
        $userId = (int)$userId;
        $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 100;
        $offset = isset($_GET['offset']) ? (int)$_GET['offset'] : 0;

        $stmt = $this->db->prepare("
            SELECT
                c.id,
                c.user_a_id,
                c.user_b_id,
                c.last_message_at,
                c.last_message_id,
                c.is_anonymous,
                c.anonymous_alias,
                c.anonymous_participant_id,
                ua.username as user_a_name,
                ua.avatar_url as user_a_avatar,
                ub.username as user_b_name,
                ub.avatar_url as user_b_avatar,
                CASE WHEN c.user_a_id = ? THEN ub.id ELSE ua.id END as partner_id,
                CASE WHEN c.user_a_id = ? THEN ub.username ELSE ua.username END as partner_real_name,
                CASE WHEN c.user_a_id = ? THEN ub.avatar_url ELSE ua.avatar_url END as partner_avatar_url,
                m.body_text as last_message_text,
                m.sender_alias as last_msg_alias,
                m.is_anonymous as last_msg_is_anon
            FROM conversations c
            JOIN users ua ON c.user_a_id = ua.id
            JOIN users ub ON c.user_b_id = ub.id
            LEFT JOIN messages m ON c.last_message_id = m.id
            WHERE c.user_a_id = ? OR c.user_b_id = ?
            ORDER BY c.last_message_at DESC
            LIMIT ? OFFSET ?
        ");
        $stmt->bindValue(1, $userId, PDO::PARAM_INT);
        $stmt->bindValue(2, $userId, PDO::PARAM_INT);
        $stmt->bindValue(3, $userId, PDO::PARAM_INT);
        $stmt->bindValue(4, $userId, PDO::PARAM_INT);
        $stmt->bindValue(5, $userId, PDO::PARAM_INT);
        $stmt->bindValue(6, $limit, PDO::PARAM_INT);
        $stmt->bindValue(7, $offset, PDO::PARAM_INT);
        $stmt->execute();

        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        foreach ($rows as &$row) {
            $row['is_anonymous'] = ((int)($row['is_anonymous'] ?? 0) === 1);
            $row['last_msg_is_anon'] = ((int)($row['last_msg_is_anon'] ?? 0) === 1);
            $row['display_alias'] = $row['is_anonymous'] ? ($row['anonymous_alias'] ?? null) : null;
        }
        unset($row);

        $this->json($rows);
    }

    public function getConversationMessages($id) {
        AdminMiddleware::authenticate();
        $stmt = $this->db->prepare("
            SELECT 
                m.*,
                u.username as sender_real_name,
                u.avatar_url as sender_avatar,
                u.is_seed as sender_is_bot
            FROM messages m
            JOIN users u ON m.sender_id = u.id
            WHERE m.conversation_id = ?
            ORDER BY m.created_at ASC
        ");
        $stmt->execute([$id]);

        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        foreach ($rows as &$row) {
            $alias = isset($row['sender_alias']) ? trim((string)$row['sender_alias']) : '';
            $asPart = $alias !== '' ? " (as '{$alias}')" : '';
            $body = isset($row['body_text']) ? (string)$row['body_text'] : '';
            $row['sender_name'] = $row['sender_real_name'];
            $row['admin_display'] = '[' . $row['sender_real_name'] . ']' . $asPart . ': ' . $body;
        }
        unset($row);

        $this->json($rows);
    }

    public function deleteMessage($id) {
        $admin = AdminMiddleware::authenticate();
        $stmt = $this->db->prepare("DELETE FROM messages WHERE id = ?");
        $stmt->execute([$id]);
        $this->logAudit($admin['id'], 'delete_message', 'messages', $id);
        $this->json(['success' => true]);
    }

    public function sendMessageAsAdmin() {
        $admin = AdminMiddleware::authenticate();
        $input = $this->input();
        
        $conversationId = isset($input['conversation_id']) ? $input['conversation_id'] : null;
        $recipientId = isset($input['recipient_id']) ? $input['recipient_id'] : null;
        $text = $input['body_text'];
        $asBotId = isset($input['as_bot_id']) ? $input['as_bot_id'] : null;
        
        $senderId = $asBotId ? $asBotId : $admin['id']; // Default to Admin ID if no bot selected (might need schema support)

        if (!$conversationId && !$recipientId) {
             $this->json(['error' => 'Must specify conversation_id or recipient_id'], 422);
        }

        if ($conversationId) {
            // Get participants to find receiver
            $stmt = $this->db->prepare("SELECT user_a_id, user_b_id FROM conversations WHERE id = ?");
            $stmt->execute([$conversationId]);
            $conv = $stmt->fetch();
            if (!$conv) $this->json(['error' => 'Conversation not found'], 404);
            
            // If acting as a bot, ensure bot is in conversation
            if ($asBotId) {
                if ($conv['user_a_id'] == $asBotId) $recipientId = $conv['user_b_id'];
                elseif ($conv['user_b_id'] == $asBotId) $recipientId = $conv['user_a_id'];
                else {
                    // Bot is not in this conversation! Admin is intervening.
                    // Who is the recipient? Maybe we shouldn't send *as* the bot here if the bot isn't part of it.
                    // Or we send as System.
                    // For now, let's default to sending to User A if not specified? No, dangerous.
                    // Let's assume User B is the target if not specified.
                    $recipientId = $conv['user_b_id']; // Fallback
                }
            } else {
                 // System message to both? or just insert without receiver?
                 // Schema requires receiver.
                 $recipientId = $conv['user_b_id']; // Fallback
            }
        } else {
            // Existing logic for recipient_id
            // ... (Create conversation logic)
            // Re-using logic from MessageController would be better but keeping it simple here.
             $stmtConv = $this->db->prepare("SELECT id FROM conversations WHERE (user_a_id = ? AND user_b_id = ?) OR (user_a_id = ? AND user_b_id = ?)");
             $stmtConv->execute([$senderId, $recipientId, $recipientId, $senderId]);
             $conv = $stmtConv->fetch();
             if (!$conv) {
                 $stmtC = $this->db->prepare("INSERT INTO conversations (user_a_id, user_b_id, created_at, updated_at) VALUES (?, ?, NOW(), NOW())");
                 $stmtC->execute([$senderId, $recipientId]);
                 $conversationId = $this->db->lastInsertId();
             } else {
                 $conversationId = $conv['id'];
             }
        }

        $stmt = $this->db->prepare("INSERT INTO messages (conversation_id, sender_id, receiver_id, body_text, sent_by_admin_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, NOW(), NOW())");
        $stmt->execute([$conversationId, $senderId, $recipientId, $text, $admin['id']]);
        
        // Update conversation last_message
        $msgId = $this->db->lastInsertId();
        $this->db->prepare("UPDATE conversations SET last_message_at = NOW(), last_message_id = ? WHERE id = ?")->execute([$msgId, $conversationId]);
        
        $this->logAudit($admin['id'], 'send_message', 'users', $recipientId, ['text' => $text, 'as_bot' => $senderId]);
        $this->json(['success' => true]);
    }

    public function getDashboardStats() {
        AdminMiddleware::authenticate();
        
        $stats = [];
        $stats['total_users'] = $this->db->query("SELECT COUNT(*) FROM users")->fetchColumn();
        $stats['new_users_today'] = $this->db->query("SELECT COUNT(*) FROM users WHERE DATE(created_at) = CURDATE()")->fetchColumn();
        $stats['active_conversations'] = $this->db->query("SELECT COUNT(*) FROM conversations WHERE last_message_at > DATE_SUB(NOW(), INTERVAL 24 HOUR)")->fetchColumn();
        $stats['messages_today'] = $this->db->query("SELECT COUNT(*) FROM messages WHERE DATE(created_at) = CURDATE()")->fetchColumn();
        $stats['pending_reports'] = $this->db->query("SELECT COUNT(*) FROM reports WHERE status = 'open'")->fetchColumn();
        
        $this->json($stats);
    }

    public function banUser($id) {
        $admin = AdminMiddleware::authenticate();
        $input = $this->input();
        $reason = isset($input['reason']) ? $input['reason'] : 'Banned by admin';

        $stmt = $this->db->prepare("UPDATE users SET is_banned = 1, ban_reason = ? WHERE id = ?");
        $stmt->execute([$reason, $id]);

        $this->logAudit($admin['id'], 'ban_user', 'users', $id, ['reason' => $reason]);
        $this->json(['success' => true]);
    }

    public function unbanUser($id) {
        $admin = AdminMiddleware::authenticate();

        $stmt = $this->db->prepare("UPDATE users SET is_banned = 0, ban_reason = NULL WHERE id = ?");
        $stmt->execute([$id]);

        $this->logAudit($admin['id'], 'unban_user', 'users', $id);
        $this->json(['success' => true]);
    }

    public function updateSubscription($id) {
        $admin = AdminMiddleware::authenticate();
        $input = $this->input();

        $isPlus = isset($input['is_plus_subscriber']) ? (int)$input['is_plus_subscriber'] : 0;
        $plusExpiresAt = !empty($input['plus_expires_at']) ? str_replace('T', ' ', $input['plus_expires_at']) : null;
        $activeFrame = !empty($input['active_frame']) ? $input['active_frame'] : null;

        $stmt = $this->db->prepare("
            UPDATE users SET 
                is_plus_subscriber = ?, 
                plus_expires_at = ?,
                active_frame = ?,
                updated_at = NOW() 
            WHERE id = ?
        ");
        $stmt->execute([$isPlus, $plusExpiresAt, $activeFrame, $id]);

        $this->logAudit($admin['id'], 'update_subscription', 'users', $id, $input);
        $this->json(['success' => true]);
    }

    public function addBoost($id) {
        $admin = AdminMiddleware::authenticate();
        $input = $this->input();
        
        if (empty($input['minutes'])) {
            $this->json(['error' => 'Minutes required'], 422);
        }

        $minutes = (int)$input['minutes'];
        
        // Get current boost status
        $stmt = $this->db->prepare("SELECT boosted_until FROM users WHERE id = ?");
        $stmt->execute([$id]);
        $currentBoost = $stmt->fetchColumn();
        
        $baseTime = (strtotime($currentBoost) > time()) ? strtotime($currentBoost) : time();
        $newBoostTime = date('Y-m-d H:i:s', $baseTime + ($minutes * 60));

        $stmt = $this->db->prepare("UPDATE users SET boosted_until = ? WHERE id = ?");
        $stmt->execute([$newBoostTime, $id]);

        $this->logAudit($admin['id'], 'add_boost', 'users', $id, ['minutes' => $minutes, 'new_until' => $newBoostTime]);
        $this->json(['success' => true, 'boosted_until' => $newBoostTime]);
    }

    public function getReports() {
        AdminMiddleware::authenticate();
        $stmt = $this->db->prepare("
            SELECT r.*,
                   u1.username as reporter_name,
                   u2.username as reported_name,
                   u1.avatar_url as reporter_avatar,
                   u2.avatar_url as reported_avatar
            FROM reports r 
            LEFT JOIN users u1 ON r.reporter_id = u1.id 
            LEFT JOIN users u2 ON r.reported_user_id = u2.id 
            WHERE r.status = 'open' 
            ORDER BY r.created_at ASC
        ");
        $stmt->execute();
        $this->json($stmt->fetchAll(PDO::FETCH_ASSOC));
    }

    public function closeReport($id) {
        $admin = AdminMiddleware::authenticate();
        $stmt = $this->db->prepare("UPDATE reports SET status = 'closed', updated_at = NOW() WHERE id = ?");
        $stmt->execute([$id]);
        
        $this->logAudit($admin['id'], 'close_report', 'reports', $id);
        $this->json(['success' => true]);
    }

    public function getStories() {
        AdminMiddleware::authenticate();
        $stmt = $this->db->prepare("SELECT s.*, u.username FROM stories s JOIN users u ON s.user_id = u.id ORDER BY s.created_at DESC LIMIT 50");
        $stmt->execute();
        $this->json($stmt->fetchAll());
    }

    public function deleteStory($id) {
        $admin = AdminMiddleware::authenticate();
        $stmt = $this->db->prepare("DELETE FROM stories WHERE id = ?");
        $stmt->execute([$id]);

        $this->logAudit($admin['id'], 'delete_story', 'stories', $id);
        $this->json(['success' => true]);
    }
    
    public function getSubscriptions() {
        AdminMiddleware::authenticate();
        $stmt = $this->db->prepare("SELECT s.*, u.username FROM subscriptions s JOIN users u ON s.user_id = u.id ORDER BY s.created_at DESC LIMIT 50");
        $stmt->execute();
        $this->json($stmt->fetchAll());
    }

    public function broadcast() {
        $admin = AdminMiddleware::authenticate();
        $input = $this->input();
        $this->validate($input, ['title' => 'required', 'message' => 'required']);

        $this->oneSignal->broadcast($input['title'], $input['message'], isset($input['data_json']) ? $input['data_json'] : []);
        
        $this->logAudit($admin['id'], 'broadcast', 'notifications', null, ['title' => $input['title']]);
        $this->json(['success' => true]);
    }

    private function logAudit($adminId, $action, $targetType, $targetId = null, $meta = []) {
        $stmt = $this->db->prepare("INSERT INTO admin_audit_logs (admin_id, action, target_type, target_id, meta_json, created_at) VALUES (?, ?, ?, ?, ?, NOW())");
        $stmt->execute([$adminId, $action, $targetType, $targetId, json_encode($meta)]);
    }
}
