import os
UPLOAD_FOLDER = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../data/images'))
import os

from PIL import Image as PILImage, UnidentifiedImageError
from flask import Blueprint, request, jsonify, send_file
from tinydb import Query

from api.utils import get_current_user_id, sanitize_email, get_validated_user_id
from config.paths import get_user_image_dir

from db.db import image_db
from models.image import Image

image_api = Blueprint('image_api', __name__)
ALLOWED_EXTENSIONS = {'jpg', 'jpeg', 'png'}
IMAGE_TYPE_PROFILE = 1
IMAGE_TYPE_ICON = 2
MAX_DIMENSION = 512

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

@image_api.route('/image/upload', methods=['POST'])
def upload():
    user_id = get_validated_user_id()
    if not user_id:
        return jsonify({'error': 'Unauthorized', 'code': 'UNAUTHORIZED'}), 401
    if 'file' not in request.files:
        return jsonify({'error': 'No file part in the request'}), 400
    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': 'No selected file'}), 400

    image_type = request.form.get('type', None)
    if not image_type:
        return jsonify({'error': 'Image type is required'}), 400
    try:
        image_type = int(image_type)
        if image_type not in [IMAGE_TYPE_PROFILE, IMAGE_TYPE_ICON]:
            return jsonify({'error': 'Invalid image type. Must be 1 or 2'}), 400
    except ValueError:
        return jsonify({'error': 'Image type must be an integer'}), 400

    perm = request.form.get('permanent', "false").lower() == 'true'

    if not file or not allowed_file(file.filename):
        return jsonify({'error': 'Invalid file type or no file selected'}), 400

    try:
        pil_image = PILImage.open(file.stream)
        original_format = pil_image.format  # store before convert
        pil_image.verify()  # quick integrity check
        file.stream.seek(0)
        pil_image = PILImage.open(file.stream).convert('RGBA' if pil_image.mode in ('RGBA', 'LA') else 'RGB')
    except UnidentifiedImageError:
        return jsonify({'error': 'Uploaded file is not a valid image'}), 400
    except Exception:
        return jsonify({'error': 'Failed to process image'}), 400

    if original_format not in ('JPEG', 'PNG'):
        return jsonify({'error': 'Only JPEG and PNG images are allowed'}), 400

    # Resize preserving aspect ratio (in-place thumbnail)
    pil_image.thumbnail((MAX_DIMENSION, MAX_DIMENSION), PILImage.Resampling.LANCZOS)

    format_extension_map = {'JPEG': '.jpg', 'PNG': '.png'}
    extension = format_extension_map.get(original_format, '.png')
    image_record = Image(extension=extension, permanent=perm, type=image_type, user_id=user_id)
    filename = image_record.id + extension
    user_image_dir = get_user_image_dir(user_id)
    os.makedirs(user_image_dir, exist_ok=True)

    filepath = os.path.abspath(os.path.join(get_user_image_dir(sanitize_email(user_id)), filename))

    try:
        # Save with appropriate format
        save_params = {}
        if pil_image.format == 'JPEG':
            save_params['quality'] = 90
            save_params['optimize'] = True
        pil_image.save(filepath, format=pil_image.format, **save_params)
    except Exception:
        return jsonify({'error': 'Failed to save processed image'}), 500

    image_db.insert(image_record.to_dict())

    return jsonify({'message': 'Image uploaded successfully', 'filename': filename, 'id': image_record.id}), 200

@image_api.route('/image/request/<id>', methods=['GET'])
def request_image(id):
    user_id = get_validated_user_id()
    if not user_id:
        return jsonify({'error': 'Unauthorized', 'code': 'UNAUTHORIZED'}), 401
    ImageQuery = Query()
    image_record = image_db.get(ImageQuery.id == id)
    if not image_record:
        return jsonify({'error': 'Image not found'}), 404
    image = Image.from_dict(image_record)
    # Allow if image.user_id is None (public image), or matches user_id
    if image.user_id is not None and image.user_id != user_id:
        return jsonify({'error': 'Forbidden: image does not belong to user', 'code': 'FORBIDDEN'}), 403
    filename = f"{image.id}{image.extension}"
    if image.user_id is None:
        filepath = os.path.abspath(os.path.join(get_user_image_dir("default"), filename))
    else:
        filepath = os.path.abspath(os.path.join(get_user_image_dir(image.user_id), filename))
    if not os.path.exists(filepath):
        return jsonify({'error': 'File not found'}), 404
    return send_file(filepath)

@image_api.route('/image/list', methods=['GET'])
def list_images():
    user_id = get_validated_user_id()
    if not user_id:
        return jsonify({'error': 'Unauthorized', 'code': 'UNAUTHORIZED'}), 401
    image_type = request.args.get('type', type=int)
    ImageQuery = Query()
    if image_type is not None:
        if image_type not in [IMAGE_TYPE_PROFILE, IMAGE_TYPE_ICON]:
            return jsonify({'error': 'Invalid image type'}), 400
        images = image_db.search((ImageQuery.type == image_type) & ((ImageQuery.user_id == user_id) | (ImageQuery.user_id == None)))
    else:
        images = image_db.search((ImageQuery.user_id == user_id) | (ImageQuery.user_id == None))
    image_ids = [img['id'] for img in images]
    return jsonify({'ids': image_ids, 'count': len(image_ids)}), 200
