#!/usr/bin/env python3
"""Mobile Wallpaper Processor - Flask Web Service
Skaliert, Schneidet zu und entfernt Text aus Bildern für 1440x3120 Displays
"""

import os
import cv2
import numpy as np
import uuid
import time
from datetime import datetime, timedelta
from flask import Flask, render_template, request, send_file, jsonify, url_for
from werkzeug.utils import secure_filename
from PIL import Image, ImageEnhance
import easyocr
import threading

# Konfiguration
TARGET_WIDTH = 1440
TARGET_HEIGHT = 3120
TARGET_ASPECT = TARGET_WIDTH / TARGET_HEIGHT
UPLOAD_FOLDER = 'static/uploads'
DOWNLOAD_FOLDER = 'static/downloads'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp', 'tiff'}
MAX_FILE_SIZE = 50 * 1024 * 1024  # 50MB

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['DOWNLOAD_FOLDER'] = DOWNLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = MAX_FILE_SIZE

# Globaler OCR Reader (wird einmal geladen)
ocr_reader = None
def get_ocr_reader():
    global ocr_reader
    if ocr_reader is None:
        print("Lade OCR Model...")
        ocr_reader = easyocr.Reader(['de', 'en'], gpu=False)
    return ocr_reader

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

def cleanup_old_files():
    """Löscht Dateien älter als 1 Stunde"""
    cutoff = datetime.now() - timedelta(hours=1)
    for folder in [UPLOAD_FOLDER, DOWNLOAD_FOLDER]:
        for filename in os.listdir(folder):
            filepath = os.path.join(folder, filename)
            try:
                if os.path.isfile(filepath):
                    file_time = datetime.fromtimestamp(os.path.getmtime(filepath))
                    if file_time < cutoff:
                        os.remove(filepath)
            except Exception as e:
                print(f"Cleanup error: {e}")

def smart_crop(img_array, target_width, target_height):
    """Intelligentes Zuschneiden mit Fokus auf Bildzentrum"""
    img = Image.fromarray(cv2.cvtColor(img_array, cv2.COLOR_BGR2RGB))
    original_width, original_height = img.size
    target_aspect = target_width / target_height
    original_aspect = original_width / original_height
    
    if original_aspect > target_aspect:
        # Bild ist breiter als Ziel: Horizontal zuschneiden
        new_width = int(original_height * target_aspect)
        left = (original_width - new_width) // 2
        img_cropped = img.crop((left, 0, left + new_width, original_height))
    else:
        # Bild ist höher als Ziel: Vertikal zuschneiden
        new_height = int(original_width / target_aspect)
        top = (original_height - new_height) // 2
        img_cropped = img.crop((0, top, original_width, top + new_height))
    
    # Auf Zielgröße skalieren
    img_resized = img_cropped.resize((target_width, target_height), Image.Resampling.LANCZOS)
    return cv2.cvtColor(np.array(img_resized), cv2.COLOR_RGB2BGR)

def detect_text_regions(img):
    """Erkennt Textbereiche im Bild mit OCR"""
    reader = get_ocr_reader()
    results = reader.readtext(img)
    
    mask = np.zeros(img.shape[:2], dtype=np.uint8)
    detected_boxes = []
    
    for (bbox, text, conf) in results:
        if conf > 0.3:  # Nur Text mit ausreichender Konfidenz
            # bbox sind 4 Punkte: [[x1,y1], [x2,y2], [x3,y3], [x4,y4]]
            pts = np.array(bbox, np.int32)
            # Erweitere Box um Padding
            x_coords = [p[0] for p in bbox]
            y_coords = [p[1] for p in bbox]
            x_min, x_max = max(0, min(x_coords) - 10), min(img.shape[1], max(x_coords) + 10)
            y_min, y_max = max(0, min(y_coords) - 10), min(img.shape[0], max(y_coords) + 10)
            
            cv2.rectangle(mask, (x_min, y_min), (x_max, y_max), 255, -1)
            detected_boxes.append({'text': text, 'confidence': conf, 'box': [x_min, y_min, x_max, y_max]})
    
    return mask, detected_boxes

def remove_text_inpaint(img, mask):
    """Entfernt Text durch OpenCV Inpainting"""
    if np.sum(mask) == 0:
        return img
    
    # Telea Inpainting - gut für kleine strukturierte Bereiche wie Text
    result = cv2.inpaint(img, mask, 3, cv2.INPAINT_TELEA)
    return result

def auto_enhance(img):
    """Automatische Bildverbesserung"""
    pil_img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    
    # Kontrast leicht erhöhen
    enhancer = ImageEnhance.Contrast(pil_img)
    pil_img = enhancer.enhance(1.1)
    
    # Sättigung leicht erhöhen
    enhancer = ImageEnhance.Color(pil_img)
    pil_img = enhancer.enhance(1.1)
    
    # Schärfen
    enhancer = ImageEnhance.Sharpness(pil_img)
    pil_img = enhancer.enhance(1.2)
    
    return cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)

def process_image(input_path, remove_text=True):
    """Hauptverarbeitungs-Pipeline"""
    
    # Bild laden
    img = cv2.imread(input_path)
    if img is None:
        raise ValueError("Bild konnte nicht geladen werden")
    
    # Optional: Text entfernen
    if remove_text:
        mask, detected_text = detect_text_regions(img)
        if len(detected_text) > 0:
            img = remove_text_inpaint(img, mask)
    
    # Smart Crop auf Zielauflösung
    img_processed = smart_crop(img, TARGET_WIDTH, TARGET_HEIGHT)
    
    # Auto-Enhance
    img_processed = auto_enhance(img_processed)
    
    return img_processed

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return jsonify({'error': 'Keine Datei hochgeladen'}), 400
    
    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': 'Keine Datei ausgewählt'}), 400
    
    if not allowed_file(file.filename):
        return jsonify({'error': 'Dateiformat nicht erlaubt. Erlaubt: ' + str(ALLOWED_EXTENSIONS)}), 400
    
    try:
        # Cleanup alte Dateien
        cleanup_old_files()
        
        # Eindeutigen Dateinamen generieren
        filename = str(uuid.uuid4())[:8] + '_' + secure_filename(file.filename)
        input_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        file.save(input_path)
        
        # Optionen
        remove_text = request.form.get('remove_text', 'true').lower() == 'true'
        
        # Bild verarbeiten
        processed = process_image(input_path, remove_text=remove_text)
        
        # Ausgabedatei
        output_filename = 'processed_' + os.path.splitext(filename)[0] + '.jpg'
        output_path = os.path.join(app.config['DOWNLOAD_FOLDER'], output_filename)
        cv2.imwrite(output_path, processed, [cv2.IMWRITE_JPEG_QUALITY, 95])
        
        # Original löschen
        os.remove(input_path)
        
        return jsonify({
            'success': True,
            'download_url': url_for('download_file', filename=output_filename),
            'preview_url': '/' + output_path,
            'message': f'Bild verarbeitet: {TARGET_WIDTH}x{TARGET_HEIGHT}px'
        })
        
    except Exception as e:
        print(f"Error: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/download/<filename>')
def download_file(filename):
    return send_file(os.path.join(app.config['DOWNLOAD_FOLDER'], filename), 
                    as_attachment=True, download_name='wallpaper_1440x3120.jpg')

@app.route('/cleanup', methods=['POST'])
def manual_cleanup():
    cleanup_old_files()
    return jsonify({'success': True, 'message': 'Aufgeräumt'})

if __name__ == '__main__':
    print(f"Starting Mobile Wallpaper Service...")
    print(f"Zielauflösung: {TARGET_WIDTH}x{TARGET_HEIGHT} ({TARGET_ASPECT:.3f})")
    app.run(host='0.0.0.0', port=5000, debug=True)
