import sys
import os
import json
import inspect
import socket
import tempfile
from pathlib import Path
from datetime import datetime
from http.server import HTTPServer, BaseHTTPRequestHandler
from socketserver import ThreadingMixIn
import threading
import base64

from PyQt6.QtWidgets import (QApplication, QMainWindow, QMessageBox,
                             QTextEdit, QVBoxLayout, QWidget, QPushButton,
                             QLabel, QHBoxLayout, QSpinBox)
from PyQt6.QtCore import Qt, pyqtSignal, pyqtSlot, QTimer
from PyQt6.QtGui import QMovie, QTextCursor
from PyQt6.uic import loadUi
from win32com.client import CDispatch, Dispatch

# Proje modüllerini import et
sys.path.append(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()) + "\\..\\..")))
_current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
_project_root = os.path.dirname(os.path.dirname(os.path.dirname(_current_dir)))
sys.path.insert(0, _project_root)
sys.path.insert(0, _current_dir)

from IFikatia import IFikatia
from IDokuman import IDokuman
from IDialoglar.IDialogCevirici.threadManager import Async


class CeviriciRequestHandler(BaseHTTPRequestHandler):
    """
    HTTP Request Handler - WRL Dönüştürme İsteklerini İşler

    POST /convert - Dosya dönüştürme isteği
    GET /status - Server durumu
    GET /health - Health check
    """

    def log_message(self, format, *args):
        """Log mesajlarını ana dialog'a gönder"""
        message = f"{self.address_string()} - {format % args}"
        if hasattr(self.server, 'dialog_window'):
            self.server.dialog_window.log_signal.emit(message)

    def do_GET(self):
        """GET istekleri - Durum kontrolü"""
        if self.path == '/status':
            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            self.end_headers()

            status = {
                'status': 'running',
                'server': 'IDialogCevirici',
                'version': '1.0',
                'timestamp': datetime.now().isoformat(),
                'catia_connected': hasattr(self.server, 'catia_app') and self.server.catia_app is not None
            }
            self.wfile.write(json.dumps(status, ensure_ascii=False).encode('utf-8'))

        elif self.path == '/health':
            self.send_response(200)
            self.send_header('Content-type', 'text/plain')
            self.end_headers()
            self.wfile.write(b'OK')

        else:
            self.send_response(404)
            self.end_headers()
            self.wfile.write(b'Not Found')

    def do_POST(self):
        """POST istekleri - Dosya dönüştürme"""
        if self.path == '/convert':
            try:
                # İstek gövdesini oku
                content_length = int(self.headers['Content-Length'])
                post_data = self.rfile.read(content_length)
                request_data = json.loads(post_data.decode('utf-8'))

                # Gerekli parametreleri al
                source_file = request_data.get('source_file')
                output_dir = request_data.get('output_dir', tempfile.gettempdir())
                output_name = request_data.get('output_name', 'converted')

                if not source_file:
                    self.send_error(400, "source_file parametresi gerekli")
                    return

                if not os.path.exists(source_file):
                    self.send_error(404, f"Kaynak dosya bulunamadı: {source_file}")
                    return

                # CATIA ile dosyayı aç ve WRL'e dönüştür
                result = self.server.convert_to_wrl(source_file, output_dir, output_name)

                # Başarılı yanıt
                self.send_response(200)
                self.send_header('Content-type', 'application/json')
                self.end_headers()

                response = {
                    'success': True,
                    'source_file': source_file,
                    'output_file': result['output_file'],
                    'timestamp': datetime.now().isoformat()
                }

                self.wfile.write(json.dumps(response, ensure_ascii=False).encode('utf-8'))

            except Exception as e:
                self.send_error(500, f"Dönüştürme hatası: {str(e)}")
                if hasattr(self.server, 'dialog_window'):
                    self.server.dialog_window.log_signal.emit(f"HATA: {str(e)}")

        else:
            self.send_response(404)
            self.end_headers()
            self.wfile.write(b'Not Found')


class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    """Thread'li HTTP Server - Her istek ayrı thread'de işlenir"""
    daemon_threads = True

    def __init__(self, server_address, RequestHandlerClass, catia_app=None, dialog_window=None):
        self.catia_app = catia_app
        self.dialog_window = dialog_window
        super().__init__(server_address, RequestHandlerClass)

    def convert_to_wrl(self, source_file, output_dir, output_name):
        """
        CATIA dosyasını WRL formatına dönüştür

        Args:
            source_file: Kaynak CATIA dosyası (.CATPart, .CATProduct, vb.)
            output_dir: Çıktı klasörü
            output_name: Çıktı dosya adı (uzantısız)

        Returns:
            dict: {'output_file': 'tam/dosya/yolu.wrl'}
        """
        import pythoncom
        import traceback as tb

        try:
            # COM Thread başlat
            pythoncom.CoInitialize()

            if self.dialog_window:
                self.dialog_window.log_signal.emit(f"Dönüştürme başladı: {source_file}")

            # CATIA uygulamasını al
            if not self.catia_app:
                raise Exception("CATIA bağlantısı yok!")

            fikatia = IFikatia(obj=self.catia_app)

            # Çıktı dosya yolunu oluştur
            output_file = os.path.join(output_dir, f"{output_name}.wrl")

            # Aktif dökümanı kullan (zaten açık olan dosya)
            aktif_dokuman = fikatia.aktifDokuman

            if not aktif_dokuman:
                raise Exception("CATIA'da aktif döküman yok!")

            if self.dialog_window:
                self.dialog_window.log_signal.emit(f"WRL export başlıyor...")

            # WRL formatına dönüştür
            aktif_dokuman.veriAktar(output_file, "wrl")

            if self.dialog_window:
                self.dialog_window.log_signal.emit(f"✓ Dönüştürüldü: {output_file}")

            return {'output_file': output_file}

        except Exception as e:
            error_msg = f"✗ Hata: {str(e)}"
            error_detail = ''.join(tb.format_exc())

            if self.dialog_window:
                self.dialog_window.log_signal.emit(error_msg)
                self.dialog_window.log_signal.emit(f"Detay: {error_detail[:200]}")

            raise

        finally:
            try:
                pythoncom.CoUninitialize()
            except:
                pass


class IDialogCevirici(QMainWindow):
    """
    FikoYT Dialog Çevirici - CATIA WRL Dönüştürme Servisi

    HTTP Server ile CATIA dosyalarını WRL formatına dönüştürür.
    PyQt6 UI ile server durumunu ve logları gösterir.
    """

    log_signal = pyqtSignal(str)  # Log mesajları için sinyal

    def __init__(self, parent=None, flags=None, Catia=None):
        """
        Dialog constructor

        Args:
            parent: Parent widget (None - standalone)
            flags: Qt window flags
            Catia: CATIA COM Application nesnesi
        """
        # CATIA COM nesnesi kontrolü
        if Catia is None:
            raise ValueError("CATIA parametresi boş olamaz!")

        # PyQt6 initialization
        if not QApplication.instance():
            self.app = QApplication([sys.argv])
        else:
            self.app = QApplication.instance()

        # Default flags ayarla
        if flags is None:
            flags = Qt.WindowType.Window

        super(IDialogCevirici, self).__init__(None)

        # CATIA COM nesnesi sarmalama
        self.__fikatia = IFikatia(obj=Catia)
        self.__catia_app = Catia

        # Script dosyasının yolu
        self.ScriptYolu = str(Path(__file__).parent)

        # Server değişkenleri
        self.server = None
        self.server_thread = None
        self.server_port = 1989
        self.server_running = False

        # UI oluştur (programatik olarak - .ui dosyası yoksa)
        self.init_ui()

        # Log sinyalini bağla
        self.log_signal.connect(self.append_log)

        # Pencere özelliklerini ayarla
        self.setWindowFlags(
            Qt.WindowType.Window |
            Qt.WindowType.WindowCloseButtonHint |
            Qt.WindowType.CustomizeWindowHint |
            Qt.WindowType.WindowStaysOnTopHint
        )

        self.setWindowTitle("FikoYT - Dialog Çevirici Server")
        self.resize(800, 600)

    def init_ui(self):
        """UI bileşenlerini oluştur"""
        # Ana widget
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        # Ana layout
        main_layout = QVBoxLayout(central_widget)

        # Başlık
        title_label = QLabel("FikoYT Dialog Çevirici - WRL Dönüştürme Servisi")
        title_label.setStyleSheet("font-size: 18px; font-weight: bold; padding: 10px;")
        title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        main_layout.addWidget(title_label)

        # Server kontrol paneli
        control_layout = QHBoxLayout()

        # Port ayarı
        port_label = QLabel("Port:")
        control_layout.addWidget(port_label)

        self.port_spinbox = QSpinBox()
        self.port_spinbox.setRange(1024, 65535)
        self.port_spinbox.setValue(self.server_port)
        self.port_spinbox.valueChanged.connect(self.on_port_changed)
        control_layout.addWidget(self.port_spinbox)

        # Başlat butonu
        self.btn_start = QPushButton("Server Başlat")
        self.btn_start.clicked.connect(self.start_server)
        self.btn_start.setStyleSheet("background-color: #4CAF50; color: white; padding: 8px;")
        control_layout.addWidget(self.btn_start)

        # Durdur butonu
        self.btn_stop = QPushButton("Server Durdur")
        self.btn_stop.clicked.connect(self.stop_server)
        self.btn_stop.setEnabled(False)
        self.btn_stop.setStyleSheet("background-color: #f44336; color: white; padding: 8px;")
        control_layout.addWidget(self.btn_stop)

        control_layout.addStretch()
        main_layout.addLayout(control_layout)

        # Durum label
        self.status_label = QLabel("Durum: Server kapalı")
        self.status_label.setStyleSheet("padding: 10px; font-size: 14px; color: #666;")
        main_layout.addWidget(self.status_label)

        # Log alanı
        log_label = QLabel("Server Logları:")
        log_label.setStyleSheet("font-weight: bold; padding: 5px;")
        main_layout.addWidget(log_label)

        self.log_text = QTextEdit()
        self.log_text.setReadOnly(True)
        self.log_text.setStyleSheet("background-color: #1e1e1e; color: #00ff00; font-family: monospace;")
        main_layout.addWidget(self.log_text)

        # Temizle butonu
        btn_clear_log = QPushButton("Logları Temizle")
        btn_clear_log.clicked.connect(self.clear_log)
        main_layout.addWidget(btn_clear_log)

    @pyqtSlot()
    def on_port_changed(self):
        """Port değiştiğinde"""
        if not self.server_running:
            self.server_port = self.port_spinbox.value()

    @pyqtSlot()
    def start_server(self):
        """HTTP Server'ı başlat"""
        try:
            if self.server_running:
                self.append_log("⚠ Server zaten çalışıyor!")
                return

            # Server'ı ayrı thread'de başlat
            @Async()
            def start_http_server(catia_app, port, dialog_window):
                try:
                    server_address = ('', port)
                    httpd = ThreadedHTTPServer(
                        server_address,
                        CeviriciRequestHandler,
                        catia_app=catia_app,
                        dialog_window=dialog_window
                    )

                    dialog_window.server = httpd
                    dialog_window.server_running = True

                    dialog_window.log_signal.emit(f"✓ Server başlatıldı: http://localhost:{port}")
                    dialog_window.log_signal.emit(f"  - Status: http://localhost:{port}/status")
                    dialog_window.log_signal.emit(f"  - Health: http://localhost:{port}/health")
                    dialog_window.log_signal.emit(f"  - Convert: POST http://localhost:{port}/convert")

                    # Server'ı çalıştır (blocking call)
                    httpd.serve_forever()

                except Exception as e:
                    dialog_window.log_signal.emit(f"✗ Server başlatma hatası: {str(e)}")
                    dialog_window.server_running = False

            # Thread'i başlat
            start_http_server(self.__catia_app, self.server_port, self)

            # UI güncelle
            self.btn_start.setEnabled(False)
            self.btn_stop.setEnabled(True)
            self.port_spinbox.setEnabled(False)
            self.status_label.setText(f"Durum: Server çalışıyor (Port: {self.server_port})")
            self.status_label.setStyleSheet("padding: 10px; font-size: 14px; color: #4CAF50; font-weight: bold;")

        except Exception as e:
            QMessageBox.critical(self, "Hata", f"Server başlatılamadı: {str(e)}")
            self.append_log(f"✗ Server başlatma hatası: {str(e)}")

    @pyqtSlot()
    def stop_server(self):
        """HTTP Server'ı durdur"""
        try:
            if not self.server_running:
                self.append_log("⚠ Server zaten durmuş!")
                return

            if self.server:
                self.server.shutdown()
                self.server = None
                self.server_running = False

                self.append_log("✓ Server durduruldu")

                # UI güncelle
                self.btn_start.setEnabled(True)
                self.btn_stop.setEnabled(False)
                self.port_spinbox.setEnabled(True)
                self.status_label.setText("Durum: Server kapalı")
                self.status_label.setStyleSheet("padding: 10px; font-size: 14px; color: #666;")

        except Exception as e:
            QMessageBox.critical(self, "Hata", f"Server durdurulamadı: {str(e)}")
            self.append_log(f"✗ Server durdurma hatası: {str(e)}")

    @pyqtSlot(str)
    def append_log(self, message):
        """Log mesajı ekle"""
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_entry = f"[{timestamp}] {message}"
        self.log_text.append(log_entry)

        # En alta scroll
        cursor = self.log_text.textCursor()
        cursor.movePosition(QTextCursor.MoveOperation.End)
        self.log_text.setTextCursor(cursor)

    @pyqtSlot()
    def clear_log(self):
        """Logları temizle"""
        self.log_text.clear()
        self.append_log("Loglar temizlendi")

    @pyqtSlot()
    def show(self):
        """Pencereyi göster"""
        super(IDialogCevirici, self).show()
        self.append_log("FikoYT Dialog Çevirici başlatıldı")
        self.append_log(f"CATIA bağlantısı: {'✓ Aktif' if self.__catia_app else '✗ Yok'}")

    def closeEvent(self, event):
        """Pencere kapatılırken"""
        if self.server_running:
            reply = QMessageBox.question(
                self,
                'Çıkış',
                "Server çalışıyor. Kapatmak istediğinizden emin misiniz?",
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
                QMessageBox.StandardButton.No
            )

            if reply == QMessageBox.StandardButton.Yes:
                self.stop_server()
                event.accept()
            else:
                event.ignore()
        else:
            event.accept()


if __name__ == '__main__':
    import win32com.client

    app = QApplication(sys.argv)
    app.setStyle("fusion")

    try:
        # CATIA'yı başlat
        catia = win32com.client.Dispatch("Catia.Application")

        # Dialog'u oluştur
        dialog = IDialogCevirici(Catia=catia)
        dialog.show()

        sys.exit(app.exec())

    except Exception as e:
        print(f"Hata: {e}")
        QMessageBox.critical(None, "Hata", f"CATIA bağlantısı kurulamadı: {str(e)}")
