#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
FreeCAD API Server - Flask REST API Wrapper for free.py
HTTP endpoint to analyze STEP files using FreeCAD
"""

from flask import Flask, request, jsonify, send_file
from werkzeug.utils import secure_filename
import os
import sys
import json
import tempfile
import traceback
import subprocess
from pathlib import Path

# free.py modülünü import et
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import free

app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 500 * 1024 * 1024  # 500MB max file size

# Upload klasörü
UPLOAD_FOLDER = tempfile.gettempdir()
ALLOWED_EXTENSIONS = {'stp', 'step'}

def allowed_file(filename):
    """Dosya uzantısı kontrolü"""
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


@app.route('/health', methods=['GET'])
def health_check():
    """Health check endpoint"""
    return jsonify({
        'status': 'ok',
        'service': 'FreeCAD API Server',
        'version': '1.0.0'
    }), 200


@app.route('/analyze', methods=['POST'])
def analyze_step_file():
    """
    STEP dosyasını analiz et

    Request:
        - Multipart form-data
        - file: STEP dosyası (.stp/.step)
        - material (optional): Malzeme tipi (default: aluminium)
        - density (optional): Özel yoğunluk (kg/dm³)
        - precision (optional): Ondalık hassasiyet

    Response:
        - JSON formatında analiz sonuçları
    """
    try:
        # Dosya kontrolü
        if 'file' not in request.files:
            return jsonify({
                'success': False,
                'error': 'No file part in request',
                'message': 'STEP dosyası gönderilmedi'
            }), 400

        file = request.files['file']

        if file.filename == '':
            return jsonify({
                'success': False,
                'error': 'No selected file',
                'message': 'Dosya seçilmedi'
            }), 400

        if not allowed_file(file.filename):
            return jsonify({
                'success': False,
                'error': 'Invalid file type',
                'message': 'Sadece .stp ve .step dosyaları kabul edilir'
            }), 400

        # Güvenli dosya adı
        filename = secure_filename(file.filename)

        # Geçici dosya oluştur
        with tempfile.NamedTemporaryFile(delete=False, suffix='.stp') as temp_file:
            temp_path = temp_file.name
            file.save(temp_path)

        # Parametreleri al
        material_name = request.form.get('material', 'aluminium')
        custom_density = request.form.get('density', None)
        precision = request.form.get('precision', None)

        # Konfigürasyon hazırla
        material_cfg = free.MATERIALS.get(material_name, free.MATERIALS['aluminium'])

        if custom_density:
            try:
                density_value = float(custom_density)
                material_cfg = free.MaterialConfig(
                    name=f"Custom ({density_value} kg/dm³)",
                    density_kg_dm3=density_value,
                    symbol="Custom"
                )
            except ValueError:
                pass

        analysis_cfg = free.AnalysisConfig()
        if precision:
            try:
                analysis_cfg.decimal_precision = int(precision)
            except ValueError:
                pass

        output_cfg = free.OutputConfig(
            output_dir=tempfile.gettempdir(),
            save_json=False,  # JSON'u response olarak döndüreceğiz
            save_detailed_debug=False
        )

        units_cfg = free.UnitsConfig()

        # Analiz et
        try:
            analyzer = free.FreeCADAnalyzer(
                material_cfg,
                analysis_cfg,
                output_cfg,
                units_cfg
            )

            summary = analyzer.analyze_file(temp_path)

            # Geçici dosyayı sil
            try:
                os.unlink(temp_path)
            except:
                pass

            # Başarılı response
            return jsonify({
                'success': True,
                'data': summary,
                'message': 'Analiz başarıyla tamamlandı'
            }), 200

        except Exception as e:
            # Analiz hatası
            # Geçici dosyayı sil
            try:
                os.unlink(temp_path)
            except:
                pass

            return jsonify({
                'success': False,
                'error': str(e),
                'message': 'FreeCAD analiz hatası',
                'traceback': traceback.format_exc() if app.debug else None
            }), 500

    except Exception as e:
        # Genel hata
        return jsonify({
            'success': False,
            'error': str(e),
            'message': 'Beklenmeyen hata oluştu',
            'traceback': traceback.format_exc() if app.debug else None
        }), 500


@app.route('/materials', methods=['GET'])
def list_materials():
    """Mevcut malzeme listesini döndür"""
    materials_list = []
    for key, mat in free.MATERIALS.items():
        materials_list.append({
            'key': key,
            'name': mat.name,
            'symbol': mat.symbol,
            'density_kg_dm3': mat.density_kg_dm3
        })

    return jsonify({
        'success': True,
        'materials': materials_list
    }), 200


@app.route('/render', methods=['POST'])
def render_step_file():
    """
    STEP dosyasından GIF render oluştur

    Request:
        - Multipart form-data
        - file: STEP dosyası (.stp/.step)
        - width (optional): Görüntü genişliği (default: 1920)
        - height (optional): Görüntü yüksekliği (default: 1080)
        - frames (optional): Frame sayısı (default: 36)
        - fps (optional): FPS (default: 12)
        - yaw (optional): Y ekseni dönüş (default: true)
        - pitch (optional): X ekseni dönüş (default: true)

    Response:
        - GIF dosyası (binary stream)
    """
    try:
        # Dosya kontrolü
        if 'file' not in request.files:
            return jsonify({
                'success': False,
                'error': 'No file part in request',
                'message': 'STEP dosyası gönderilmedi'
            }), 400

        file = request.files['file']

        if file.filename == '':
            return jsonify({
                'success': False,
                'error': 'No selected file',
                'message': 'Dosya seçilmedi'
            }), 400

        if not allowed_file(file.filename):
            return jsonify({
                'success': False,
                'error': 'Invalid file type',
                'message': 'Sadece .stp ve .step dosyaları kabul edilir'
            }), 400

        # Güvenli dosya adı
        filename = secure_filename(file.filename)

        # Geçici dosya ve dizin
        temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.stp')
        temp_path = temp_file.name
        file.save(temp_path)
        temp_file.close()

        output_dir = tempfile.mkdtemp()
        gif_path = os.path.join(output_dir, 'render.gif')

        try:
            # Parametreleri al - Görüntü boyutları
            width = int(request.form.get('width', 800))
            height = int(request.form.get('height', 600))

            # Kamera ayarları
            zoom = float(request.form.get('zoom', 1.0))
            view_type = request.form.get('view_type', 'axonometric')
            background_color = request.form.get('background_color', 'White')

            # Animasyon ayarları
            rotation_speed = int(request.form.get('rotation_speed', 5))
            num_frames = int(request.form.get('num_frames', 36))
            fps = int(request.form.get('fps', 12))

            # Rotasyon eksenleri
            yaw_enabled = request.form.get('yaw_enabled', 'true').lower() == 'true'
            pitch_enabled = request.form.get('pitch_enabled', 'true').lower() == 'true'
            roll_enabled = request.form.get('roll_enabled', 'false').lower() == 'true'

            # Rotasyon açı aralıkları
            yaw_range = json.loads(request.form.get('yaw_range', '[0, 360]'))
            pitch_range = json.loads(request.form.get('pitch_range', '[0, 360]'))
            roll_range = json.loads(request.form.get('roll_range', '[0, 360]'))

            # GIF ayarları
            gif_optimize = request.form.get('gif_optimize', 'true').lower() == 'true'
            gif_quality = int(request.form.get('gif_quality', 85))
            pause_duration = float(request.form.get('pause_duration', 0.5))
            loop = int(request.form.get('loop', 0))

            # Frame duration hesapla (rotation_speed'e göre)
            base_duration = 0.08
            duration = base_duration / (rotation_speed / 5.0)

            print(f"[RENDER] Parametreler: {width}x{height}, zoom={zoom}, view={view_type}, bg={background_color}", flush=True)
            print(f"[RENDER] Animasyon: frames={num_frames}, fps={fps}, speed={rotation_speed}x", flush=True)
            print(f"[RENDER] Rotasyon: yaw={yaw_enabled}, pitch={pitch_enabled}, roll={roll_enabled}", flush=True)
            print(f"[RENDER] GIF: optimize={gif_optimize}, quality={gif_quality}, loop={loop}", flush=True)

            # freesim-yatay-dikey.py scriptini çağır
            script_dir = os.path.dirname(os.path.abspath(__file__))
            script_path = os.path.join(script_dir, 'freesim-yatay-dikey.py')

            # JSON config oluştur
            config_path = os.path.join(output_dir, 'render_config.json')
            config = {
                "input_file": temp_path,
                "render": {
                    "width": width,
                    "height": height,
                    "background": background_color,
                    "view_type": view_type
                },
                "animation": {
                    "enabled": True,
                    "num_frames": num_frames,
                    "angle_step": 360 / num_frames,  # Frame sayısına göre açı adımı
                    "duration": duration,
                    "pause_duration": pause_duration,
                    "loop": loop,
                    "fps": fps,
                    "yaw_enabled": yaw_enabled,
                    "pitch_enabled": pitch_enabled,
                    "roll_enabled": roll_enabled,
                    "yaw_range": yaw_range,
                    "pitch_range": pitch_range,
                    "roll_range": roll_range
                },
                "output": {
                    "output_dir": output_dir,
                    "base_name": "render",
                    "save_png": False,
                    "save_gif": True,
                    "save_frames": False,
                    "gif_optimize": gif_optimize,
                    "gif_quality": gif_quality
                },
                "camera": {
                    "zoom_level": zoom * 1.5,  # Kullanıcı zoom'u uygula
                    "camera_position": None,
                    "look_at": None
                },
                "render_params": {
                    "rotation_speed": rotation_speed
                }
            }

            with open(config_path, 'w', encoding='utf-8') as f:
                json.dump(config, f, indent=2)

            # xvfb-run ile render scripti çalıştır
            cmd = [
                'xvfb-run',
                '-a',
                '-s', '-screen 0 1920x1080x24',
                'python3',
                script_path,
                '-c', config_path
            ]

            result = subprocess.run(
                cmd,
                capture_output=True,
                text=True,
                timeout=300  # 5 dakika timeout
            )

            if result.returncode != 0:
                raise Exception(f"Render hatası:\nStderr: {result.stderr}\nStdout: {result.stdout}")

            # GIF kontrolü
            if not os.path.exists(gif_path):
                raise Exception(f"GIF oluşturulamadı. Output: {result.stdout}\nError: {result.stderr}")

            # GIF boyutu kontrol
            gif_size = os.path.getsize(gif_path)
            print(f"[RENDER] GIF oluşturuldu: {gif_path} ({gif_size} bytes)", flush=True)

            # GIF'i gönder
            return send_file(
                gif_path,
                mimetype='image/gif',
                as_attachment=True,
                download_name=f"{os.path.splitext(filename)[0]}.gif"
            )

        except Exception as e:
            # Hata durumunda temizlik
            error_msg = str(e)
            tb = traceback.format_exc()

            print(f"\n{'='*60}")
            print("RENDER HATASI:")
            print(f"{'='*60}")
            print(tb)
            print(f"{'='*60}\n")

            # Temizlik
            try:
                if os.path.exists(temp_path):
                    os.unlink(temp_path)
            except:
                pass

            try:
                import shutil
                if os.path.exists(output_dir):
                    shutil.rmtree(output_dir)
            except:
                pass

            return jsonify({
                'success': False,
                'error': error_msg,
                'message': 'Render hatası oluştu',
                'traceback': tb if app.debug else None
            }), 500

    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e),
            'message': 'Beklenmeyen hata oluştu',
            'traceback': traceback.format_exc() if app.debug else None
        }), 500


if __name__ == '__main__':
    port = int(os.getenv('FREECAD_API_PORT', '8090'))
    debug = True  # Debug modunu aç

    print(f"""
╔══════════════════════════════════════════════════════════════╗
║         FreeCAD API Server - FikoYT                          ║
║──────────────────────────────────────────────────────────────║
║  Port        : {port}                                             ║
║  Debug       : {debug}                                           ║
║  Max File    : 500MB                                         ║
║  Endpoints   :                                               ║
║    - GET  /health        (Health check)                      ║
║    - POST /analyze       (STEP file analysis)                ║
║    - GET  /materials     (List available materials)          ║
║    - POST /render        (STEP file GIF render)              ║
╚══════════════════════════════════════════════════════════════╝
    """)

    app.run(
        host='0.0.0.0',
        port=port,
        debug=debug,
        threaded=True
    )
