# Copyright 2026 Espressif Systems (Shanghai) Co., Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse
import json
import os
import sys

from esp_viewer.core.engine import EspViewerEngine
from esp_viewer.core.logger import setup_logger


def main():
    # Primary directory for examples
    example_dir = os.path.join(os.path.dirname(__file__), "assets", "examples")
    # Legacy/Default profiles
    profile_dir = os.path.join(os.path.dirname(__file__), "assets", "profiles")

    parser = argparse.ArgumentParser(description="ESP Viewer Generic Launcher")
    parser.add_argument(
        "--profile", type=str, help="Path to a JSON profile to load directly"
    )
    parser.add_argument(
        "--dir", type=str, help="Default profiles directory", default=example_dir
    )
    parser.add_argument(
        "--web",
        action="store_true",
        help="Launch the Web API server instead of the native PySide UI",
    )
    parser.add_argument(
        "--web-port",
        type=int,
        default=8080,
        help="Port to run the Web API server on (default: 8080)",
    )
    parser.add_argument(
        "--force",
        action="store_true",
        help="Force clear the bound web port before starting (Linux)",
    )
    parser.add_argument("--mock", action="store_true", help="Force mock device mode")
    parser.add_argument("--debug", action="store_true", help="Enable debug logging")
    parser.add_argument("--port", type=str, help="Specific serial port to connect to automatically")
    args = parser.parse_args()

    logger = setup_logger(debug_mode=args.debug)
    logger.info("Initializing ESP Viewer Launcher")

    profile_path = None
    if args.profile:
        abs_path = os.path.abspath(args.profile)
        if os.path.exists(abs_path):
            profile_path = abs_path
        else:
            # Try relative to default profiles dir
            fallback = os.path.join(profile_dir, args.profile)
            if os.path.exists(fallback):
                profile_path = fallback
            else:
                logger.error(f"Error: Profile not found at {args.profile}")
                sys.exit(1)
    else:
        # Launch Launcher to let user select (Requires PySide GUI)
        from PySide6.QtWidgets import QApplication, QDialog

        from esp_viewer.ui.launcher import Launcher

        app = QApplication.instance() or QApplication(sys.argv)
        launcher = Launcher(args.dir)
        if launcher.exec_() == QDialog.Accepted:
            profile_path = launcher.selected_profile_path
        else:
            sys.exit(0)

    if profile_path:
        with open(profile_path, "r") as f:
            profile = json.load(f)
            # Store filepath for potential updates
            profile["_filepath"] = profile_path

        if args.mock:
            if "connection" not in profile:
                profile["connection"] = {}
            profile["connection"]["port"] = "MOCK"
            logger.info("Forcing MOCK device mode via CLI flag")
        elif args.port:
            if "connection" not in profile:
                profile["connection"] = {}
            profile["connection"]["port"] = args.port
            logger.info(f"Forcing connection strictly on {args.port} via CLI flag")

        # 1. Initialize Core Engine
        engine = EspViewerEngine(profile)

        if args.web:
            from esp_viewer.web.web_adapter import WebAdapter

            # 2a. Initialize Frontend Adapter (Web/FastAPI)
            port = args.web_port
            adapter = WebAdapter(port=port)
            engine.add_adapter(adapter)
            engine.start()

            if args.force:
                logger.info(
                    f"Force flag detected. Attempting to kill ghost processes on port {port}..."
                )
                os.system(f"fuser -k {port}/tcp > /dev/null 2>&1")
                import time

                time.sleep(1)  # Give OS time to recycle the socket

            logger.info(f"Starting ESP Viewer Web API at http://0.0.0.0:{port}")
            print("Access the UI via web browser. Press Ctrl+C to exit.")
            try:
                adapter.start_server()
            except KeyboardInterrupt:
                pass
            finally:
                engine.stop()
                sys.exit(0)
        else:
            # 2b. Initialize Frontend Adapter (PySide)
            from PySide6.QtWidgets import QApplication
            from esp_viewer.ui.generic_window import GenericWindow
            from esp_viewer.ui.pyside_adapter import PySideAdapter

            app = QApplication.instance() or QApplication(sys.argv)
            adapter = PySideAdapter()
            engine.add_adapter(adapter)
            engine.start()

            # Initialize the UI and inject the adapter
            window = GenericWindow(profile, adapter)
            window.show()

            # Run GUI loop and ensure clean shutdown
            ret = app.exec_()
            engine.stop()
            sys.exit(ret)
    else:
        logger.error("Error: No profile selected.")
        sys.exit(1)


if __name__ == "__main__":
    main()
