import os
import traceback
import bcrypt
from flask import request, jsonify
from PIL import Image
from werkzeug.utils import secure_filename
from db_config import get_db_connection

UPLOAD_FOLDER = "/var/www/wisegym.app/api/data/pfp"
ALLOWED_EXTENSIONS = {"png", "jpg", "jpeg", "gif"}

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

def get_user_by_id(user_id):
    try:
        conn = get_db_connection()
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
        user = cursor.fetchone()
        cursor.close()
        conn.close()
        if user:
            user.pop("password_hash", None)
            return jsonify(user)
        return jsonify({"error": "User not found"}), 404
    except Exception as e:
        return jsonify({"error": str(e)}), 500

def get_user_by_username(username):
    try:
        conn = get_db_connection()
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT * FROM users WHERE username = %s", (username,))
        user = cursor.fetchone()
        cursor.close()
        conn.close()
        if user:
            user.pop("password_hash", None)
            return jsonify(user)
        return jsonify({"error": "User not found"}), 404
    except Exception as e:
        return jsonify({"error": str(e)}), 500

def get_users_by_display_name(name):
    try:
        conn = get_db_connection()
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT * FROM users WHERE display_name LIKE %s", (f"%{name}%",))
        users = cursor.fetchall()
        for u in users:
            u.pop("password_hash", None)
        cursor.close()
        conn.close()
        return jsonify(users)
    except Exception as e:
        return jsonify({"error": str(e)}), 500

def register_user():
    try:
        data = request.json
        username = data["username"]
        password = data.get("password")
        display_name = data.get("displayName") or username
        is_google = data.get("isGoogleSignIn", False)

        conn = get_db_connection()
        cursor = conn.cursor(dictionary=True)

        # Check if username already exists
        cursor.execute("SELECT id FROM users WHERE username = %s", (username,))
        if cursor.fetchone():
            cursor.close()
            conn.close()
            return jsonify({"error": "Username already exists"}), 400

        if is_google:
            # Insert Google user without password
            cursor.execute(
                "INSERT INTO users (username, password_hash, display_name, is_google_signin) VALUES (%s, %s, %s, %s)",
                (username, None, display_name, True)
            )
        else:
            if not password:
                return jsonify({"error": "Password required"}), 400

            hashed_pw = bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()
            cursor.execute(
                "INSERT INTO users (username, password_hash, display_name, is_google_signin) VALUES (%s, %s, %s, %s)",
                (username, hashed_pw, display_name, False)
            )

        conn.commit()

        # Fetch and return created user (without password)
        cursor.execute("SELECT * FROM users WHERE username = %s", (username,))
        new_user = cursor.fetchone()
        new_user.pop("password_hash", None)

        cursor.close()
        conn.close()
        return jsonify(new_user), 200

    except Exception as e:
        return jsonify({"error": str(e)}), 500


def login_user():
    try:
        data = request.json
        username = data.get("username")
        password = data.get("password", "")
        is_google = data.get("isGoogleSignIn", False)

        if not username:
            return jsonify({"error": "Username is required"}), 400

        if not is_google and not password:
            return jsonify({"error": "Password is required"}), 400

        conn = get_db_connection()
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT * FROM users WHERE username = %s", (username,))
        user = cursor.fetchone()
        cursor.close()
        conn.close()

        if not user:
            return jsonify({"error": "User not found"}), 404

        if is_google:
            if user["password_hash"] is not None:
                return jsonify({"error": "Account is not a Google user"}), 403
        else:
            if user["password_hash"] is None or not bcrypt.checkpw(password.encode(), user["password_hash"].encode()):
                return jsonify({"error": "Incorrect password"}), 401

        user.pop("password_hash", None)
        return jsonify(user), 200

    except Exception as e:
        return jsonify({"error": str(e)}), 500


def delete_user():
    try:
        data = request.json
        user_id = data.get("user_id")
        if not user_id:
            return jsonify({"error": "Missing user_id"}), 400

        conn = get_db_connection()
        cursor = conn.cursor()
        cursor.execute("DELETE FROM users WHERE id = %s", (user_id,))
        conn.commit()
        cursor.close()
        conn.close()
        return jsonify({"status": "User deleted"}), 200
    except Exception as e:
        return jsonify({"error": str(e)}), 500

def filter_users():
    try:
        role = request.args.get("role")
        notifications = request.args.get("notifications")
        data_sharing = request.args.get("data_sharing")
        emails = request.args.get("emails")
        visibility = request.args.get("account_visibility")
        fcm_token_set = request.args.get("fcm_token")

        query = "SELECT * FROM users"
        conditions = []
        values = []

        if role:
            conditions.append("role = %s")
            values.append(role)
        if notifications in ("0", "1"):
            conditions.append("notifications = %s")
            values.append(notifications)
        if data_sharing in ("0", "1"):
            conditions.append("data_sharing = %s")
            values.append(data_sharing)
        if emails in ("0", "1"):
            conditions.append("emails = %s")
            values.append(emails)
        if visibility:
            conditions.append("account_visibility = %s")
            values.append(visibility)
        if fcm_token_set == "1":
            conditions.append("fcm_token IS NOT NULL")
        elif fcm_token_set == "0":
            conditions.append("fcm_token IS NULL")

        if conditions:
            query += " WHERE " + " AND ".join(conditions)

        conn = get_db_connection()
        cursor = conn.cursor(dictionary=True)
        cursor.execute(query, tuple(values))
        users = cursor.fetchall()

        for user in users:
            user.pop("password_hash", None)

        cursor.close()
        conn.close()
        return jsonify(users)

    except Exception as e:
        return jsonify({"error": str(e)}), 500

def upload_profile_picture():
    try:
        if 'file' not in request.files or 'username' not in request.form:
            return jsonify({"error": "Missing file or username"}), 400

        file = request.files['file']
        username = request.form['username']

        # 🔍 Lookup user ID
        conn = get_db_connection()
        cursor = conn.cursor()
        cursor.execute("SELECT id FROM users WHERE username = %s", (username,))
        user = cursor.fetchone()
        if not user:
            cursor.close()
            conn.close()
            return jsonify({"error": "User not found"}), 404
        user_id = user[0]
        cursor.close()
        conn.close()

        if file.filename == '' or not allowed_file(file.filename):
            return jsonify({"error": "Invalid file"}), 400
        if not file.mimetype.startswith('image/'):
            return jsonify({"error": "Invalid file type. Only images allowed."}), 400

        ext = file.filename.rsplit('.', 1)[1].lower()
        safe_base = secure_filename(f"user_{user_id}_pfp")
        filename = f"{safe_base}.{ext}"
        save_path = os.path.join(UPLOAD_FOLDER, filename)

        # 🔁 Remove any existing profile picture formats for this user
        for existing_ext in ALLOWED_EXTENSIONS:
            old_path = os.path.join(UPLOAD_FOLDER, f"{safe_base}.{existing_ext}")
            if os.path.exists(old_path):
                os.remove(old_path)

        file.save(save_path)

        try:
            with Image.open(save_path) as img:
                width, height = img.size
                if width < 50 or height < 50:
                    os.remove(save_path)
                    return jsonify({"error": "Image too small. Min size: 50x50px."}), 400
                if width > 1024 or height > 1024:
                    os.remove(save_path)
                    return jsonify({"error": "Image too large. Max size: 1024x1024px."}), 400
        except Exception:
            os.remove(save_path)
            return jsonify({"error": "Invalid image format."}), 400

        image_url = f"https://api.wisegym.app/data/pfp/{filename}"
        try:
            conn = get_db_connection()
            cursor = conn.cursor()
            cursor.execute("UPDATE users SET profile_picture = %s WHERE id = %s", (image_url, user_id))
            conn.commit()
            cursor.close()
            conn.close()
        except Exception as db_error:
            os.remove(save_path)
            return jsonify({"error": "Failed to update user in database", "details": str(db_error)}), 500

        return jsonify({
            "status": "success",
            "file": filename,
            "url": image_url
        }), 200

    except Exception as e:
        traceback.print_exc()
        return jsonify({"error": "Internal error", "details": str(e)}), 500

def get_profile_picture(username):
    try:
        conn = get_db_connection()
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT profile_picture FROM users WHERE username = %s", (username,))
        result = cursor.fetchone()
        cursor.close()
        conn.close()

        if not result or not result["profile_picture"]:
            return jsonify({"error": "No profile picture found"}), 404

        return jsonify({
            "username": username,
            "profile_picture": result["profile_picture"]
        }), 200

    except Exception as e:
        return jsonify({"error": str(e)}), 500

def update_user_field():
    try:
        data = request.json
        user_id = data.get("user_id")
        field = data.get("field")
        value = data.get("value")

        if not user_id or not field:
            return jsonify({"error": "Missing user_id or field"}), 400

        if field == "password_hash":
            if not isinstance(value, str) or len(value.strip()) < 8:
                return jsonify({"error": "Password must be at least 8 characters"}), 400
            value = bcrypt.hashpw(value.encode(), bcrypt.gensalt()).decode()

        conn = get_db_connection()
        cursor = conn.cursor()
        cursor.execute(f"UPDATE users SET {field} = %s WHERE id = %s", (value, user_id))
        conn.commit()
        cursor.close()
        conn.close()

        return jsonify({"status": "User field updated"}), 200

    except Exception as e:
        return jsonify({"error": str(e)}), 500
