import os
import psycopg2
from psycopg2.extras import RealDictCursor
from psycopg2 import errors


def get_db_connection():
    """Get database connection"""
    return psycopg2.connect(
        host=os.getenv("DB_HOST", "localhost"),
        port=int(os.getenv("DB_PORT", "5432")),
        database=os.getenv("DB_NAME", "recipes_db"),
        user=os.getenv("DB_USER", "recipes_user"),
        password=os.getenv("DB_PASSWORD", "recipes_password"),
    )


# ============= Friends System =============

def send_friend_request(sender_id: int, receiver_id: int):
    """Send a friend request"""
    conn = get_db_connection()
    cur = conn.cursor(cursor_factory=RealDictCursor)
    try:
        # Check if already friends
        cur.execute(
            "SELECT 1 FROM friendships WHERE (user_id = %s AND friend_id = %s) OR (user_id = %s AND friend_id = %s)",
            (sender_id, receiver_id, receiver_id, sender_id)
        )
        if cur.fetchone():
            return {"error": "Already friends"}
        
        # Check if request already exists
        cur.execute(
            "SELECT * FROM friend_requests WHERE sender_id = %s AND receiver_id = %s AND status = 'pending'",
            (sender_id, receiver_id)
        )
        existing = cur.fetchone()
        if existing:
            return dict(existing)
        
        try:
            cur.execute(
                """
                INSERT INTO friend_requests (sender_id, receiver_id)
                VALUES (%s, %s)
                RETURNING id, sender_id, receiver_id, status, created_at
                """,
                (sender_id, receiver_id)
            )
            request = cur.fetchone()
            conn.commit()
            return dict(request)
        except errors.UniqueViolation:
            # Request already exists, fetch and return it
            conn.rollback()
            cur.execute(
                "SELECT id, sender_id, receiver_id, status, created_at FROM friend_requests WHERE sender_id = %s AND receiver_id = %s",
                (sender_id, receiver_id)
            )
            existing_request = cur.fetchone()
            if existing_request:
                return dict(existing_request)
            return {"error": "Friend request already exists"}
    finally:
        cur.close()
        conn.close()


def accept_friend_request(request_id: int):
    """Accept a friend request and create friendship"""
    conn = get_db_connection()
    cur = conn.cursor(cursor_factory=RealDictCursor)
    try:
        # Get request details
        cur.execute(
            "SELECT sender_id, receiver_id FROM friend_requests WHERE id = %s AND status = 'pending'",
            (request_id,)
        )
        request = cur.fetchone()
        if not request:
            return {"error": "Request not found or already processed"}
        
        sender_id = request["sender_id"]
        receiver_id = request["receiver_id"]
        
        # Create bidirectional friendship
        cur.execute(
            "INSERT INTO friendships (user_id, friend_id) VALUES (%s, %s), (%s, %s) ON CONFLICT DO NOTHING",
            (sender_id, receiver_id, receiver_id, sender_id)
        )
        
        # Update request status
        cur.execute(
            "UPDATE friend_requests SET status = 'accepted', updated_at = CURRENT_TIMESTAMP WHERE id = %s",
            (request_id,)
        )
        
        conn.commit()
        return {"success": True}
    finally:
        cur.close()
        conn.close()


def reject_friend_request(request_id: int):
    """Reject a friend request"""
    conn = get_db_connection()
    cur = conn.cursor()
    try:
        cur.execute(
            "UPDATE friend_requests SET status = 'rejected', updated_at = CURRENT_TIMESTAMP WHERE id = %s AND status = 'pending'",
            (request_id,)
        )
        conn.commit()
        return {"success": True}
    finally:
        cur.close()
        conn.close()


def get_friend_requests(user_id: int):
    """Get pending friend requests for a user"""
    conn = get_db_connection()
    cur = conn.cursor(cursor_factory=RealDictCursor)
    try:
        cur.execute(
            """
            SELECT fr.id AS request_id, fr.sender_id, fr.receiver_id, fr.status, fr.created_at,
                   u.username AS sender_username, u.display_name AS sender_display_name, u.email AS sender_email
            FROM friend_requests fr
            JOIN users u ON u.id = fr.sender_id
            WHERE fr.receiver_id = %s AND fr.status = 'pending'
            ORDER BY fr.created_at DESC
            """,
            (user_id,)
        )
        return [dict(row) for row in cur.fetchall()]
    finally:
        cur.close()
        conn.close()


def get_friends(user_id: int):
    """Get list of user's friends"""
    conn = get_db_connection()
    cur = conn.cursor(cursor_factory=RealDictCursor)
    try:
        cur.execute(
            """
            SELECT u.id, u.username, u.display_name, u.email, f.created_at AS friends_since
            FROM friendships f
            JOIN users u ON u.id = f.friend_id
            WHERE f.user_id = %s
            ORDER BY u.display_name
            """,
            (user_id,)
        )
        return [dict(row) for row in cur.fetchall()]
    finally:
        cur.close()
        conn.close()


def remove_friend(user_id: int, friend_id: int):
    """Remove a friend"""
    conn = get_db_connection()
    cur = conn.cursor()
    try:
        cur.execute(
            "DELETE FROM friendships WHERE (user_id = %s AND friend_id = %s) OR (user_id = %s AND friend_id = %s)",
            (user_id, friend_id, friend_id, user_id)
        )
        conn.commit()
        return {"success": True}
    finally:
        cur.close()
        conn.close()


def search_users(query: str, current_user_id: int, limit: int = 20):
    """Search for users by username or display name"""
    conn = get_db_connection()
    cur = conn.cursor(cursor_factory=RealDictCursor)
    try:
        search_pattern = f"%{query}%"
        cur.execute(
            """
            SELECT u.id, u.username, u.display_name, u.email,
                   EXISTS(SELECT 1 FROM friendships WHERE user_id = %s AND friend_id = u.id) AS is_friend,
                   EXISTS(SELECT 1 FROM friend_requests WHERE sender_id = %s AND receiver_id = u.id AND status = 'pending') AS request_sent
            FROM users u
            WHERE (u.username ILIKE %s OR u.display_name ILIKE %s) AND u.id != %s
            ORDER BY u.display_name
            LIMIT %s
            """,
            (current_user_id, current_user_id, search_pattern, search_pattern, current_user_id, limit)
        )
        return [dict(row) for row in cur.fetchall()]
    finally:
        cur.close()
        conn.close()
