<?php

class User {
    private $pdo;

    public function __construct($pdo) {
        $this->pdo = $pdo;
    }

    public function search($currentUserId, $query) {
        if (empty($query)) return [];

        $stmt = $this->pdo->prepare("SELECT id, username FROM users WHERE username LIKE ? AND id != ? LIMIT 10");
        $stmt->execute(["%$query%", $currentUserId]);
        // Map id to _id for frontend compatibility if needed? No, frontend uses 'id' usually.
        // But Mongoose used _id. Flutter model might expect _id or id.
        // Let's check Flutter model User.fromJson.
        // It likely checks both. I'll stick to 'id' (int) and hope usage is compatible or adjust.
        // The Post model had `json['_id']`. The User model might too.
        // I will return '_id' as alias just in case.
        
        $results = $stmt->fetchAll();
        foreach ($results as &$row) {
             $row['_id'] = (string)$row['id']; // Cast to string for similarity with ObjectId
        }
        return $results;
    }

    public function sendFriendRequest($currentUserId, $data) {
        $friendName = $data['username'] ?? '';
        
        $stmt = $this->pdo->prepare("SELECT id FROM users WHERE username = ?");
        $stmt->execute([$friendName]);
        $friend = $stmt->fetch();

        if (!$friend) throw new Exception("User not found", 404);
        if ($friend['id'] == $currentUserId) throw new Exception("Cannot add yourself", 400);

        // Check if already friends or request exists
        $check = $this->pdo->prepare("SELECT status FROM friendships WHERE user_id = ? AND friend_id = ?");
        $check->execute([$currentUserId, $friend['id']]);
        $existing = $check->fetch();
        
        if ($existing) {
            if ($existing['status'] === 'accepted') {
                throw new Exception("Already friends", 400);
            } else {
                throw new Exception("Friend request already sent", 400);
            }
        }

        // Check if there's a reverse request (they sent us a request)
        $reverseCheck = $this->pdo->prepare("SELECT status FROM friendships WHERE user_id = ? AND friend_id = ?");
        $reverseCheck->execute([$friend['id'], $currentUserId]);
        $reverseRequest = $reverseCheck->fetch();
        
        if ($reverseRequest && $reverseRequest['status'] === 'pending') {
            throw new Exception("This user has already sent you a request. Accept it instead.", 400);
        }

        // Send friend request (pending status)
        $ins = $this->pdo->prepare("INSERT INTO friendships (user_id, friend_id, status) VALUES (?, ?, 'pending')");
        $ins->execute([$currentUserId, $friend['id']]);

        return ["msg" => "Friend request sent"];
    }

    public function acceptFriendRequest($currentUserId, $data) {
        $friendId = $data['friendId'] ?? '';
        
        if (empty($friendId)) throw new Exception("Friend ID required", 400);

        // Check if request exists
        $check = $this->pdo->prepare("SELECT status FROM friendships WHERE user_id = ? AND friend_id = ?");
        $check->execute([$friendId, $currentUserId]);
        $request = $check->fetch();
        
        if (!$request) throw new Exception("Friend request not found", 404);
        if ($request['status'] === 'accepted') throw new Exception("Already friends", 400);

        // Accept the request (update to accepted and create reverse relationship)
        $this->pdo->beginTransaction();
        try {
            // Update the original request to accepted
            $update = $this->pdo->prepare("UPDATE friendships SET status = 'accepted' WHERE user_id = ? AND friend_id = ?");
            $update->execute([$friendId, $currentUserId]);
            
            // Create reverse relationship
            $ins = $this->pdo->prepare("INSERT INTO friendships (user_id, friend_id, status) VALUES (?, ?, 'accepted')");
            $ins->execute([$currentUserId, $friendId]);
            
            $this->pdo->commit();
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }

        return ["msg" => "Friend request accepted"];
    }

    public function removeFriend($currentUserId, $data) {
        $friendId = $data['friendId'] ?? '';
        
        if (empty($friendId)) throw new Exception("Friend ID required", 400);

        // Remove bidirectional friendship
        $this->pdo->beginTransaction();
        try {
            $del = $this->pdo->prepare("DELETE FROM friendships WHERE (user_id = ? AND friend_id = ?) OR (user_id = ? AND friend_id = ?)");
            $del->execute([$currentUserId, $friendId, $friendId, $currentUserId]);
            $this->pdo->commit();
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }

        return ["msg" => "Friend removed"];
    }

    public function getPendingRequests($currentUserId) {
        // Get requests sent TO me (that I can accept)
        $stmt = $this->pdo->prepare("
            SELECT u.id, u.username, f.status
            FROM users u 
            JOIN friendships f ON u.id = f.user_id 
            WHERE f.friend_id = ? AND f.status = 'pending'
        ");
        $stmt->execute([$currentUserId]);
        $results = $stmt->fetchAll();
        foreach ($results as &$row) {
             $row['_id'] = (string)$row['id'];
        }
        return $results;
    }

    public function getSentRequests($currentUserId) {
        // Get requests I sent (that are pending)
        $stmt = $this->pdo->prepare("
            SELECT u.id, u.username, f.status
            FROM users u 
            JOIN friendships f ON u.id = f.friend_id 
            WHERE f.user_id = ? AND f.status = 'pending'
        ");
        $stmt->execute([$currentUserId]);
        $results = $stmt->fetchAll();
        foreach ($results as &$row) {
             $row['_id'] = (string)$row['id'];
        }
        return $results;
    }

    public function cancelFriendRequest($currentUserId, $data) {
        $friendId = $data['friendId'] ?? '';
        
        if (empty($friendId)) throw new Exception("Friend ID required", 400);

        // Delete the pending request
        $del = $this->pdo->prepare("DELETE FROM friendships WHERE user_id = ? AND friend_id = ? AND status = 'pending'");
        $del->execute([$currentUserId, $friendId]);

        return ["msg" => "Friend request cancelled"];
    }

    public function getFriends($currentUserId) {
        $stmt = $this->pdo->prepare("
            SELECT u.id, u.username 
            FROM users u 
            JOIN friendships f ON u.id = f.friend_id 
            WHERE f.user_id = ? AND f.status = 'accepted'
        ");
        $stmt->execute([$currentUserId]);
        $results = $stmt->fetchAll();
        foreach ($results as &$row) {
             $row['_id'] = (string)$row['id'];
        }
        return $results;
    }

    public function getFriendsPublicKeys($currentUserId) {
        $stmt = $this->pdo->prepare("
            SELECT 
                friend_profile.id,           -- The Friend's ID
                friend_profile.public_key    -- The Friend's Public Key
            FROM users AS friend_profile
            JOIN friendships AS link 
                ON friend_profile.id = link.friend_id
            WHERE link.user_id = ?           -- Your User ID
            AND link.status = 'accepted';
        ");
        $stmt->execute([$currentUserId]);
        $results = $stmt->fetchAll();
        error_log("Raw results from getFriendsPublicKeys for user $currentUserId: " . print_r($results, true)); // Debugging line

        $newResults = [];
        foreach ($results as &$row) {
             $newResults[$row['id']] = $row['public_key'];
        }
        error_log("Fetched friends' public keys for user $currentUserId: " . print_r($newResults, true)); // Debugging line
        return $newResults; // Force object to ensure it's a map, not an array
    }

    public function notifyFriendsOfKeyChange($currentUserId, $data) {
        // Add to the post keys db the access codes.
    }
}
