<?php

namespace App\Controllers;

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

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

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

    public function index() {
        AdminMiddleware::authenticate();
        $stmt = $this->db->prepare("
            SELECT
                u.*,
                sa.label as seed_label_meta,
                sa.is_enabled,
                (SELECT COUNT(*) FROM messages m WHERE m.receiver_id = u.id AND m.is_read = 0) as unread_count,
                (SELECT MAX(m2.created_at) FROM messages m2 WHERE m2.sender_id = u.id OR m2.receiver_id = u.id) as last_activity,
                (SELECT MAX(m3.created_at) FROM messages m3 WHERE m3.receiver_id = u.id AND m3.is_read = 0) as last_unread_at
            FROM users u
            LEFT JOIN seed_accounts sa ON u.id = sa.user_id
            WHERE u.is_seed = 1
            ORDER BY
                (unread_count > 0) DESC,
                last_unread_at DESC,
                unread_count DESC,
                last_activity DESC,
                u.created_at DESC
        ");
        $stmt->execute();
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        foreach ($rows as &$row) {
            $row['unread_count'] = (int)($row['unread_count'] ?? 0);
        }
        unset($row);
        $this->json($rows);
    }

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

        $username = trim((string)$input['username']);
        $displayName = isset($input['display_name']) ? trim((string)$input['display_name']) : $username;
        $bio = isset($input['bio']) ? (string)$input['bio'] : '';
        $labelRaw = isset($input['label']) ? trim((string)$input['label']) : '';
        $label = null;
        if ($labelRaw !== '' && strcasecmp($labelRaw, 'online') !== 0) {
            if ($labelRaw === 'Bot' || $labelRaw === 'Official') {
                $label = $labelRaw;
            }
        }
        $avatarUrl = isset($input['avatar_url']) && trim((string)$input['avatar_url']) !== ''
            ? trim((string)$input['avatar_url'])
            : "https://ui-avatars.com/api/?name=" . urlencode($displayName) . "&background=random";

        $passwordHash = password_hash('botpass', PASSWORD_BCRYPT);

        $base = preg_replace('/[^a-zA-Z0-9_]/', '_', $username);
        if ($base === '') $base = 'bot';

        $finalUsername = $base;
        $finalSlug = $base;
        $tries = 0;
        while ($tries < 30) {
            $emailCandidate = $finalUsername . rand(1000, 9999) . '@bot.local';
            $check = $this->db->prepare("SELECT 1 FROM users WHERE username = ? OR link_slug = ? OR email = ? LIMIT 1");
            $check->execute([$finalUsername, $finalSlug, $emailCandidate]);
            if (!$check->fetchColumn()) {
                $fakeEmail = $emailCandidate;
                break;
            }
            $tries++;
            $suffix = '_' . rand(10, 99);
            $finalUsername = $base . $suffix;
            $finalSlug = $base . $suffix;
        }
        if (!isset($fakeEmail)) {
            $this->json(['error' => 'Could not allocate unique bot identity'], 409);
        }

        $stmt = $this->db->prepare("
            INSERT INTO users (username, display_name, email, password_hash, avatar_url, bio, link_slug, is_seed, seed_label, seed_owner_admin_id, status, created_at, updated_at)
            VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?, ?, 'online', NOW(), NOW())
        ");
        $stmt->execute([$finalUsername, $displayName, $fakeEmail, $passwordHash, $avatarUrl, $bio, $finalSlug, $label, $admin['id']]);
        $userId = $this->db->lastInsertId();

        $stmt = $this->db->prepare("INSERT INTO seed_accounts (user_id, label, is_enabled) VALUES (?, 'Bot', 1)");
        $stmt->execute([$userId]);

        $this->json(['success' => true, 'id' => $userId, 'username' => $finalUsername]);
    }

    public function update($id) {
        $admin = AdminMiddleware::authenticate();
        $input = $this->input();
        
        // Update user
        if (isset($input['display_name'])) {
            $stmt = $this->db->prepare("UPDATE users SET display_name = ? WHERE id = ?");
            $stmt->execute([$input['display_name'], $id]);
        }
        
        if (isset($input['avatar_url'])) {
            $stmt = $this->db->prepare("UPDATE users SET avatar_url = ? WHERE id = ?");
            $stmt->execute([$input['avatar_url'], $id]);
        }
        
        if (isset($input['bio'])) {
            $stmt = $this->db->prepare("UPDATE users SET bio = ? WHERE id = ?");
            $stmt->execute([$input['bio'], $id]);
        }

        // Update seed account
        if (isset($input['label'])) {
            $stmt = $this->db->prepare("UPDATE seed_accounts SET label = ? WHERE user_id = ?");
            $stmt->execute([$input['label'], $id]);
            // Also update user seed_label
            $stmt = $this->db->prepare("UPDATE users SET seed_label = ? WHERE id = ?");
            $stmt->execute([$input['label'], $id]);
        }
        
        if (isset($input['config'])) {
            $configJson = is_array($input['config']) ? json_encode($input['config']) : $input['config'];
            $stmt = $this->db->prepare("UPDATE seed_accounts SET behavior_config_json = ? WHERE user_id = ?");
            $stmt->execute([$configJson, $id]);
        }

        $this->json(['success' => true]);
    }

    public function getInbox($id) {
        AdminMiddleware::authenticate();
        
        // Get conversations for this bot
        $stmt = $this->db->prepare("
            SELECT c.*, 
                u.username as other_user_name, u.avatar_url as other_user_avatar,
                m.body_text as last_message, m.created_at as last_message_time, m.sender_id as last_sender_id, m.is_read
            FROM conversations c
            JOIN users u ON (c.user_a_id = u.id OR c.user_b_id = u.id) AND u.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
        ");
        $stmt->execute([$id, $id, $id]);
        $conversations = $stmt->fetchAll();
        
        $this->json($conversations);
    }

    public function inbox($botId) {
        AdminMiddleware::authenticate();
        $botId = (int)$botId;

        $sql = "
            SELECT
                c.id as conversation_id,
                c.updated_at,
                c.last_message_at,
                u.username as partner_username,
                u.display_name as partner_name,
                u.avatar_url as partner_avatar,
                m.body_text as last_message,
                m.sender_id as last_sender_id
            FROM conversations c
            JOIN users u ON (CASE WHEN c.user_a_id = ? THEN c.user_b_id ELSE c.user_a_id END) = u.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
        ";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([$botId, $botId, $botId]);

        $this->json($stmt->fetchAll(PDO::FETCH_ASSOC));
    }

    public function messages($conversationId) {
        AdminMiddleware::authenticate();
        $conversationId = (int)$conversationId;

        $stmt = $this->db->prepare("
            SELECT m.*, u.username, u.display_name, u.is_seed
            FROM messages m
            LEFT JOIN users u ON m.sender_id = u.id
            WHERE m.conversation_id = ?
            ORDER BY m.created_at ASC
        ");
        $stmt->execute([$conversationId]);
        $this->json($stmt->fetchAll(PDO::FETCH_ASSOC));
    }
    
    public function getStats($id) {
        AdminMiddleware::authenticate();
        
        $stats = [];
        $stmt = $this->db->prepare("SELECT COUNT(*) FROM messages WHERE sender_id = ?");
        $stmt->execute([$id]);
        $stats['sent'] = $stmt->fetchColumn();
        
        $stmt = $this->db->prepare("SELECT COUNT(*) FROM messages WHERE receiver_id = ?");
        $stmt->execute([$id]);
        $stats['received'] = $stmt->fetchColumn();
        
        $this->json($stats);
    }

    public function delete($id = null) {
        AdminMiddleware::authenticate();

        if ($id !== null) {
            $stmt = $this->db->prepare("UPDATE seed_accounts SET is_enabled = 0 WHERE user_id = ?");
            $stmt->execute([(int)$id]);
            $this->json(['success' => true]);
        }

        $input = $this->input();
        $ids = isset($input['ids']) && is_array($input['ids']) ? $input['ids'] : [];
        $ids = array_values(array_filter(array_map('intval', $ids), function ($v) { return $v > 0; }));
        if (empty($ids)) $this->json(['error' => 'No IDs provided'], 400);

        $placeholders = implode(',', array_fill(0, count($ids), '?'));

        $stmt = $this->db->prepare("DELETE FROM messages WHERE sender_id IN ($placeholders) OR receiver_id IN ($placeholders)");
        $stmt->execute(array_merge($ids, $ids));

        $stmt = $this->db->prepare("DELETE FROM conversations WHERE user_a_id IN ($placeholders) OR user_b_id IN ($placeholders)");
        $stmt->execute(array_merge($ids, $ids));

        $stmt = $this->db->prepare("DELETE FROM users WHERE id IN ($placeholders) AND is_seed = 1");
        $stmt->execute($ids);

        $this->json(['success' => true]);
    }

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

        $seedUserId = $id;
        $receiverId = $input['receiver_id'];
        $bodyText = $input['body_text'];

        // Find or create conversation
        $stmt = $this->db->prepare("SELECT id FROM conversations WHERE (user_a_id = ? AND user_b_id = ?) OR (user_a_id = ? AND user_b_id = ?)");
        $stmt->execute([$seedUserId, $receiverId, $receiverId, $seedUserId]);
        $conv = $stmt->fetch();

        if ($conv) {
            $conversationId = $conv['id'];
        } else {
            $stmt = $this->db->prepare("INSERT INTO conversations (user_a_id, user_b_id, created_at, updated_at) VALUES (?, ?, NOW(), NOW())");
            $stmt->execute([min($seedUserId, $receiverId), max($seedUserId, $receiverId)]);
            $conversationId = $this->db->lastInsertId();
        }

        // Send Message
        $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, $seedUserId, $receiverId, $bodyText, $admin['id']]);
        $messageId = $this->db->lastInsertId();

        // Update conversation
        $stmt = $this->db->prepare("UPDATE conversations SET last_message_at = NOW(), last_message_id = ? WHERE id = ?");
        $stmt->execute([$messageId, $conversationId]);

        // Push
        $stmt = $this->db->prepare("SELECT display_name, username FROM users WHERE id = ?");
        $stmt->execute([$seedUserId]);
        $sender = $stmt->fetch();

        $title = $sender['display_name'] ?: $sender['username'];
        
        $stmt = $this->db->prepare("SELECT onesignal_player_id FROM device_players WHERE user_id = ?");
        $stmt->execute([$receiverId]);
        $device = $stmt->fetch();

        if ($device) {
            $this->oneSignal->sendToUser(
                $device['onesignal_player_id'],
                $title,
                $bodyText,
                ['conversation_id' => $conversationId, 'type' => 'message']
            );
        }

        $this->json(['success' => true]);
    }

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

        $botId = (int)$input['bot_id'];
        $conversationId = (int)$input['conversation_id'];
        $text = (string)$input['message'];

        $stmt = $this->db->prepare("SELECT user_a_id, user_b_id FROM conversations WHERE id = ?");
        $stmt->execute([$conversationId]);
        $conv = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$conv) $this->json(['error' => 'Conversation not found'], 404);

        $receiverId = ((int)$conv['user_a_id'] === $botId) ? (int)$conv['user_b_id'] : (int)$conv['user_a_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, $botId, $receiverId, $text, $admin['id']]);

        $msgId = $this->db->lastInsertId();
        $this->db->prepare("UPDATE conversations SET last_message_at = NOW(), last_message_id = ?, updated_at = NOW() WHERE id = ?")->execute([$msgId, $conversationId]);

        $stmt = $this->db->prepare("SELECT display_name, username FROM users WHERE id = ?");
        $stmt->execute([$botId]);
        $sender = $stmt->fetch(PDO::FETCH_ASSOC);

        $title = ($sender['display_name'] ?? '') !== '' ? $sender['display_name'] : ($sender['username'] ?? 'User');

        $stmt = $this->db->prepare("SELECT onesignal_player_id FROM device_players WHERE user_id = ?");
        $stmt->execute([$receiverId]);
        $device = $stmt->fetch(PDO::FETCH_ASSOC);

        if ($device && isset($device['onesignal_player_id'])) {
            $this->oneSignal->sendToUser(
                $device['onesignal_player_id'],
                $title,
                $text,
                ['conversation_id' => $conversationId, 'type' => 'message']
            );
        }

        $this->json(['success' => true]);
    }

    public function markRead() {
        AdminMiddleware::authenticate();
        $input = $this->input();
        $this->validate($input, ['bot_id' => 'required']);

        $botId = (int)$input['bot_id'];
        $conversationId = isset($input['conversation_id']) ? (int)$input['conversation_id'] : null;

        if ($conversationId) {
            $stmt = $this->db->prepare("
                UPDATE messages
                SET is_read = 1, read_at = NOW()
                WHERE receiver_id = ? AND conversation_id = ? AND is_read = 0
            ");
            $stmt->execute([$botId, $conversationId]);
        } else {
            $stmt = $this->db->prepare("
                UPDATE messages
                SET is_read = 1, read_at = NOW()
                WHERE receiver_id = ? AND is_read = 0
            ");
            $stmt->execute([$botId]);
        }

        $this->json(['success' => true, 'updated' => $stmt->rowCount()]);
    }
}
