from test_main import *
from bson import ObjectId
import pytest

def cleanup_friendship(user_id, user_id_second):
    """Supprime l'amitié entre deux utilisateurs."""
    db["friends"].delete_many({
        "$or": [
            {"user_id": user_id, "friend_user_id": user_id_second},
            {"user_id": user_id_second, "friend_user_id": user_id}
        ]
    })

@pytest.fixture(autouse=True)
def cleanup_after_test(user_id, user_id_second):
    yield
    cleanup_friendship(user_id, user_id_second)

def test_add_friend(token, token_second, user_id_second):
    # Ajouter l'ami
    response = client.post("/friend/add", 
                          json={"friend_user_id": user_id_second}, 
                          headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == 200
    data = response.json()
    assert "id" in data
    friend_id = data["id"]
    
    # Accepter la demande d'ami
    response = client.patch(
        f"/friend/{friend_id}/accept",
        headers={"Authorization": f"Bearer {token_second}"}
    )
    assert response.status_code == 200

def test_add_friend_myself(token):
    friend_data = {"friend_user_id": str(db["users"].find_one({"username": "testuser"})["_id"])}
    response = client.post("/friend/add", json=friend_data, headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == 409  # Cannot add yourself as a friend

def test_list_friends(token):
    response = client.get("/friends", headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == 200
    data = response.json()
    assert isinstance(data, list)

def test_get_friend(token, user_id, user_id_second):
    # Créer une amitié directement en base
    friend_id = db["friends"].insert_one({
        "user_id": user_id,
        "friend_user_id": user_id_second,
        "status": "accepted"
    }).inserted_id
    
    # Tester la récupération de l'ami
    response = client.get(f"/friend/{friend_id}", headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == 200
    data = response.json()
    assert "id" in data
    assert "friend_user_id" in data
    assert "status" in data
    assert data["status"] == "accepted"

def test_get_friend_wrong_format(token):
    response = client.get(f"/friend/randomIdThatDoesntExists", headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == 422

def test_get_friend_unknown_id(token):
    response = client.get(f"/friend/123456789987654321abcdef", headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == 404

def test_accept_already_accepted_friend_request(token, token_second, user_id_second):
    # Créer une demande d'ami
    response = client.post(
        "/friend/add",
        json={"friend_user_id": user_id_second},
        headers={"Authorization": f"Bearer {token}"}
    )
    friend_id = response.json()["id"]
    
    # Accepter la demande une première fois
    client.patch(
        f"/friend/{friend_id}/accept",
        headers={"Authorization": f"Bearer {token_second}"}
    )
    
    # Essayer d'accepter à nouveau
    response = client.patch(
        f"/friend/{friend_id}/accept",
        headers={"Authorization": f"Bearer {token_second}"}
    )
    assert response.status_code == 422
    assert "Friend request already accepted" in response.json()["detail"]

def test_deny_friend_request(user_id, token_second, user_id_second):
    # Créer une demande d'ami directement en base
    friend_id = db["friends"].insert_one({
        "user_id": user_id,
        "friend_user_id": user_id_second,
        "status": "pending"
    }).inserted_id
    
    # Refuser la demande
    response = client.delete(
        f"/friend/{friend_id}/deny",
        headers={"Authorization": f"Bearer {token_second}"}
    )
    assert response.status_code == 200
    assert response.json()["message"] == "Friend request denied"
    
    # Vérifier que l'amitié a bien été supprimée
    friend = db["friends"].find_one({"_id": ObjectId(friend_id)})
    assert friend is None

def test_delete_friend(token, user_id, user_id_second):
    # Créer une amitié directement en base
    friend_id = db["friends"].insert_one({
        "user_id": user_id,
        "friend_user_id": user_id_second,
        "status": "accepted"
    }).inserted_id
    
    # Supprimer l'ami via l'API
    response = client.delete(
        f"/friend/{friend_id}/delete",
        headers={"Authorization": f"Bearer {token}"}
    )
    assert response.status_code == 200
    assert response.json()["message"] == "Friend and associated pin shares deleted"
    
    # Vérifier que l'amitié a bien été supprimée
    friend = db["friends"].find_one({"_id": ObjectId(friend_id)})
    assert friend is None