# Copyright (C) 2025 AIDC-AI
#
# 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.

"""
System settings component for web UI
"""

import streamlit as st

from web.i18n import tr, get_language
from web.utils.streamlit_helpers import safe_rerun
from pixelle_video.config import config_manager


def render_advanced_settings():
    """Render system configuration (required) with 2-column layout"""
    # Check if system is configured
    is_configured = config_manager.validate()
    
    # Expand if not configured, collapse if configured
    with st.expander(tr("settings.title"), expanded=not is_configured):
        # 2-column layout: LLM | ComfyUI, followed by direct media API providers.
        llm_col, comfyui_col = st.columns(2)
        
        # ====================================================================
        # Column 1: LLM Settings
        # ====================================================================
        with llm_col:
            with st.container(border=True):
                st.markdown(f"**{tr('settings.llm.title')}**")
                
                # Quick preset selection
                from pixelle_video.llm_presets import get_preset_names, get_preset, find_preset_by_base_url_and_model
                
                # Custom at the end
                preset_names = get_preset_names() + ["Custom"]
                
                # Get current config
                current_llm = config_manager.get_llm_config()
                
                # Auto-detect which preset matches current config
                current_preset = find_preset_by_base_url_and_model(
                    current_llm["base_url"], 
                    current_llm["model"]
                )
                
                # Determine default index based on current config
                if current_preset:
                    # Current config matches a preset
                    default_index = preset_names.index(current_preset)
                else:
                    # Current config doesn't match any preset -> Custom
                    default_index = len(preset_names) - 1
                
                selected_preset = st.selectbox(
                    tr("settings.llm.quick_select"),
                    options=preset_names,
                    index=default_index,
                    help=tr("settings.llm.quick_select_help"),
                    key="llm_preset_select"
                )
                
                # Auto-fill based on selected preset
                if selected_preset != "Custom":
                    # Preset selected
                    preset_config = get_preset(selected_preset)
                    
                    # If user switched to a different preset (not current one), clear API key
                    # If it's the same as current config, keep API key
                    if selected_preset == current_preset:
                        # Same preset as saved config: keep API key
                        default_api_key = current_llm["api_key"]
                    else:
                        # Different preset: use default_api_key if provided (e.g., Ollama), otherwise clear
                        default_api_key = preset_config.get("default_api_key", "")
                    
                    default_base_url = preset_config.get("base_url", "")
                    default_model = preset_config.get("model", "")
                    
                    # Show API key URL if available
                    if preset_config.get("api_key_url"):
                        st.markdown(f"🔑 [{tr('settings.llm.get_api_key')}]({preset_config['api_key_url']})")
                else:
                    # Custom: show current saved config (if any)
                    default_api_key = current_llm["api_key"]
                    default_base_url = current_llm["base_url"]
                    default_model = current_llm["model"]
                
                st.markdown("---")
                
                # API Key (use unique key to force refresh when switching preset)
                llm_api_key = st.text_input(
                    f"{tr('settings.llm.api_key')} *",
                    value=default_api_key,
                    type="password",
                    help=tr("settings.llm.api_key_help"),
                    key=f"llm_api_key_input_{selected_preset}"
                )
                
                # Base URL (use unique key based on preset to force refresh)
                llm_base_url = st.text_input(
                    f"{tr('settings.llm.base_url')} *",
                    value=default_base_url,
                    help=tr("settings.llm.base_url_help"),
                    key=f"llm_base_url_input_{selected_preset}"
                )
                
                # Model selection with dropdown and load button
                # Initialize session state for loaded models
                if "llm_loaded_models" not in st.session_state:
                    st.session_state.llm_loaded_models = []
                
                # Build model options: Custom option + loaded models
                CUSTOM_MODEL_OPTION = f"✏️ {tr('settings.llm.custom_model')}"
                model_options = [CUSTOM_MODEL_OPTION] + st.session_state.llm_loaded_models
                
                # Determine default selection
                if default_model in st.session_state.llm_loaded_models:
                    default_model_index = model_options.index(default_model)
                else:
                    # Default model not in loaded list, use custom
                    default_model_index = 0
                
                # Model dropdown with load button on the right
                model_col, load_col, test_col = st.columns([3, 1, 1])
                
                with model_col:
                    selected_model_option = st.selectbox(
                        f"{tr('settings.llm.model')} *",
                        options=model_options,
                        index=default_model_index,
                        help=tr("settings.llm.model_help"),
                        key=f"llm_model_select_{selected_preset}"
                    )
                
                with load_col:
                    st.markdown("<div style='height: 28px'></div>", unsafe_allow_html=True)
                    load_clicked = st.button(
                        f"🔄 {tr('settings.llm.load_models')}",
                        help=tr("settings.llm.load_models_help"),
                        key="load_models_btn",
                        use_container_width=True
                    )
                
                with test_col:
                    st.markdown("<div style='height: 28px'></div>", unsafe_allow_html=True)
                    test_clicked = st.button(
                        f"🔌 {tr('settings.llm.test_connection')}",
                        help=tr("settings.llm.test_connection_help"),
                        key="test_llm_connection_btn",
                        use_container_width=True
                    )
                
                # Handle load models button click
                if load_clicked:
                    if llm_api_key and llm_base_url:
                        try:
                            from pixelle_video.utils.llm_util import fetch_available_models
                            with st.spinner(tr("settings.llm.loading_models")):
                                models = fetch_available_models(llm_api_key, llm_base_url)
                                st.session_state.llm_loaded_models = models
                                st.success(tr("settings.llm.models_loaded").replace("{count}", str(len(models))))
                                safe_rerun()
                        except Exception as e:
                            st.error(tr("settings.llm.models_load_failed").replace("{error}", str(e)))
                    else:
                        st.warning(tr("status.llm_config_incomplete"))
                
                # Handle test connection button click
                if test_clicked:
                    if llm_api_key and llm_base_url:
                        try:
                            from pixelle_video.utils.llm_util import test_llm_connection
                            with st.spinner(tr("settings.llm.loading_models")):
                                success, message, model_count = test_llm_connection(llm_api_key, llm_base_url)
                                if success:
                                    st.success(tr("settings.llm.connection_success").replace("{count}", str(model_count)))
                                else:
                                    st.error(tr("settings.llm.connection_failed").replace("{error}", message))
                        except Exception as e:
                            st.error(tr("settings.llm.connection_failed").replace("{error}", str(e)))
                    else:
                        st.warning(tr("status.llm_config_incomplete"))
                
                # If custom option selected, show text input for custom model name
                if selected_model_option == CUSTOM_MODEL_OPTION:
                    llm_model = st.text_input(
                        tr("settings.llm.custom_model_input"),
                        value=default_model,
                        help=tr("settings.llm.model_help"),
                        key=f"llm_custom_model_input_{selected_preset}"
                    )
                else:
                    llm_model = selected_model_option
        
        # ====================================================================
        # Column 2: ComfyUI Settings
        # ====================================================================
        with comfyui_col:
            with st.container(border=True):
                st.markdown(f"**{tr('settings.comfyui.title')}**")
                
                # Get current configuration
                comfyui_config = config_manager.get_comfyui_config()
                
                # Local/Self-hosted ComfyUI configuration
                st.markdown(f"**{tr('settings.comfyui.local_title')}**")
                url_col, key_col = st.columns(2)
                with url_col:
                    comfyui_url = st.text_input(
                        tr("settings.comfyui.comfyui_url"),
                        value=comfyui_config.get("comfyui_url", "http://127.0.0.1:8188"),
                        help=tr("settings.comfyui.comfyui_url_help"),
                        key="comfyui_url_input"
                    )
                with key_col:
                    comfyui_api_key = st.text_input(
                        tr("settings.comfyui.comfyui_api_key"),
                        value=comfyui_config.get("comfyui_api_key", ""),
                        type="password",
                        help=tr("settings.comfyui.comfyui_api_key_help"),
                        key="comfyui_api_key_input"
                    )
                
                # Test connection button
                if st.button(tr("btn.test_connection"), key="test_comfyui", use_container_width=True):
                    try:
                        import requests
                        response = requests.get(f"{comfyui_url}/system_stats", timeout=5)
                        if response.status_code == 200:
                            st.success(tr("status.connection_success"))
                        else:
                            st.error(tr("status.connection_failed"))
                    except Exception as e:
                        st.error(f"{tr('status.connection_failed')}: {str(e)}")
                
                st.markdown("---")
                
                # RunningHub cloud configuration
                st.markdown(f"**{tr('settings.comfyui.cloud_title')}**")
                runninghub_api_key = st.text_input(
                    tr("settings.comfyui.runninghub_api_key"),
                    value=comfyui_config.get("runninghub_api_key", ""),
                    type="password",
                    help=tr("settings.comfyui.runninghub_api_key_help"),
                    key="runninghub_api_key_input"
                )
                st.caption(
                    f"{tr('settings.comfyui.runninghub_hint')} "
                    f"[{tr('settings.comfyui.runninghub_get_api_key')}]"
                    f"(https://www.runninghub{'.cn' if get_language() == 'zh_CN' else '.ai'}/?inviteCode=bozpdlbj)"
                )
                
                # RunningHub concurrent limit and instance type (in one row)
                limit_col, instance_col = st.columns(2)
                with limit_col:
                    runninghub_concurrent_limit = st.number_input(
                        tr("settings.comfyui.runninghub_concurrent_limit"),
                        min_value=1,
                        max_value=10,
                        value=comfyui_config.get("runninghub_concurrent_limit", 1),
                        help=tr("settings.comfyui.runninghub_concurrent_limit_help"),
                        key="runninghub_concurrent_limit_input"
                    )
                with instance_col:
                    # Check if instance type is "plus" (48G VRAM enabled)
                    current_instance_type = comfyui_config.get("runninghub_instance_type") or ""
                    is_plus_enabled = current_instance_type == "plus"
                    # Instance type options with i18n
                    instance_options = [
                        tr("settings.comfyui.runninghub_instance_24g"),
                        tr("settings.comfyui.runninghub_instance_48g"),
                    ]
                    runninghub_instance_type_display = st.selectbox(
                        tr("settings.comfyui.runninghub_instance_type"),
                        options=instance_options,
                        index=1 if is_plus_enabled else 0,
                        help=tr("settings.comfyui.runninghub_instance_type_help"),
                        key="runninghub_instance_type_input"
                    )
                    # Convert display value back to actual value
                    runninghub_48g_enabled = runninghub_instance_type_display == tr("settings.comfyui.runninghub_instance_48g")

        # ====================================================================
        # Direct API media providers
        # ====================================================================
        zh = get_language() == "zh_CN"
        api_cfg = config_manager.get_api_providers_config()
        common_cfg = api_cfg.get("common", {})
        openai_cfg = api_cfg.get("openai", {})
        dashscope_cfg = api_cfg.get("dashscope", {})
        ark_cfg = api_cfg.get("ark", {})
        kling_cfg = api_cfg.get("kling", {})
        default_api_base_urls = {
            "openai": "https://api.openai.com/v1",
            "dashscope": "https://dashscope.aliyuncs.com/api/v1",
            "ark": "https://ark.cn-beijing.volces.com/api/v3",
            "kling": "https://api-beijing.klingai.com",
        }

        with st.container(border=True):
            st.markdown("**🧩 API 媒体模型**" if zh else "**🧩 API Media Models**")
            st.caption(
                "用于直连图像/视频模型，不影响上方 LLM 与 ComfyUI/RunningHub 配置。"
                if zh
                else "Used for direct image/video model calls. This does not affect the LLM or ComfyUI/RunningHub settings above."
            )

            common_col, proxy_col = st.columns(2)
            with common_col:
                api_print_model_input = st.checkbox(
                    "打印模型请求参数" if zh else "Print model request parameters",
                    value=bool(common_cfg.get("print_model_input", False)),
                    help=(
                        "调试用。开启后会在终端打印发送给图像/视频模型的 prompt、模型名和输入文件路径。"
                        if zh
                        else "For debugging. Prints prompts, model names and input file paths sent to image/video models."
                    ),
                    key="api_media_print_model_input",
                )
            with proxy_col:
                api_local_proxy = st.text_input(
                    "本地代理（可选）" if zh else "Local proxy (optional)",
                    value=common_cfg.get("local_proxy", ""),
                    placeholder="http://127.0.0.1:9090",
                    help=(
                        "仅部分提供商会使用，例如 OpenAI 图像模型。留空表示不使用代理。"
                        if zh
                        else "Only used by some providers, such as OpenAI image models. Leave blank to disable."
                    ),
                    key="api_media_local_proxy",
                )

            st.markdown("---")

            provider_col1, provider_col2 = st.columns(2)
            with provider_col1:
                st.markdown("**OpenAI / GPT Image**")
                api_openai_use_proxy = st.checkbox(
                    "OpenAI 启用代理" if zh else "Use proxy for OpenAI",
                    value=bool(openai_cfg.get("use_proxy", False)),
                    key="api_media_openai_use_proxy",
                )
                api_openai_key = st.text_input(
                    "OpenAI API Key",
                    value=openai_cfg.get("api_key", ""),
                    type="password",
                    key="api_media_openai_key",
                )
                api_openai_base_url = st.text_input(
                    "OpenAI Base URL",
                    value=openai_cfg.get("base_url") or default_api_base_urls["openai"],
                    placeholder="https://api.openai.com/v1",
                    key="api_media_openai_base_url",
                )

                st.markdown("**DashScope / Wan / HappyHorse**")
                api_dashscope_use_proxy = st.checkbox(
                    "DashScope 启用代理" if zh else "Use proxy for DashScope",
                    value=bool(dashscope_cfg.get("use_proxy", False)),
                    key="api_media_dashscope_use_proxy",
                )
                api_dashscope_key = st.text_input(
                    "DashScope API Key",
                    value=dashscope_cfg.get("api_key", ""),
                    type="password",
                    key="api_media_dashscope_key",
                )
                api_dashscope_base_url = st.text_input(
                    "DashScope Base URL",
                    value=dashscope_cfg.get("base_url") or default_api_base_urls["dashscope"],
                    placeholder="https://dashscope.aliyuncs.com/api/v1",
                    key="api_media_dashscope_base_url",
                )

            with provider_col2:
                st.markdown("**Volcengine ARK / Seedream / Seedance**")
                api_ark_use_proxy = st.checkbox(
                    "ARK 启用代理" if zh else "Use proxy for ARK",
                    value=bool(ark_cfg.get("use_proxy", False)),
                    key="api_media_ark_use_proxy",
                )
                api_ark_key = st.text_input(
                    "ARK API Key",
                    value=ark_cfg.get("api_key", ""),
                    type="password",
                    key="api_media_ark_key",
                )
                api_ark_base_url = st.text_input(
                    "ARK Base URL",
                    value=ark_cfg.get("base_url") or default_api_base_urls["ark"],
                    placeholder="https://ark.cn-beijing.volces.com/api/v3",
                    key="api_media_ark_base_url",
                )

                st.markdown("**Kling AI / 可灵**")
                api_kling_use_proxy = st.checkbox(
                    "Kling 启用代理" if zh else "Use proxy for Kling",
                    value=bool(kling_cfg.get("use_proxy", False)),
                    key="api_media_kling_use_proxy",
                )
                api_kling_base_url = st.text_input(
                    "Kling Base URL",
                    value=kling_cfg.get("base_url") or default_api_base_urls["kling"],
                    placeholder="https://api-beijing.klingai.com",
                    key="api_media_kling_base_url",
                )
                api_kling_access_key = st.text_input(
                    "Kling Access Key",
                    value=kling_cfg.get("access_key", ""),
                    type="password",
                    key="api_media_kling_access_key",
                )
                api_kling_secret_key = st.text_input(
                    "Kling Secret Key",
                    value=kling_cfg.get("secret_key", ""),
                    type="password",
                    key="api_media_kling_secret_key",
                )
        
        # ====================================================================
        # Action Buttons (full width at bottom)
        # ====================================================================
        st.markdown("---")
        
        col1, col2 = st.columns(2)
        with col1:
            if st.button(tr("btn.save_config"), use_container_width=True, key="save_config_btn"):
                try:
                    # Validate and save LLM configuration
                    if not (llm_api_key and llm_base_url and llm_model):
                        st.error(tr("status.llm_config_incomplete"))
                    else:
                        config_manager.set_llm_config(llm_api_key, llm_base_url, llm_model)
                    
                    # Save ComfyUI configuration (optional fields, always save what's provided)
                    # Convert checkbox to instance type: True -> "plus", False -> ""
                    instance_type = "plus" if runninghub_48g_enabled else ""
                    config_manager.set_comfyui_config(
                        comfyui_url=comfyui_url if comfyui_url else None,
                        comfyui_api_key=comfyui_api_key if comfyui_api_key else None,
                        runninghub_api_key=runninghub_api_key if runninghub_api_key else None,
                        runninghub_concurrent_limit=int(runninghub_concurrent_limit),
                        runninghub_instance_type=instance_type
                    )

                    # Save direct image/video API provider configuration.
                    config_manager.set_api_provider_config("common", {
                        "print_model_input": bool(api_print_model_input),
                        "local_proxy": api_local_proxy or "",
                    })
                    config_manager.set_api_provider_config("openai", {
                        "api_key": api_openai_key or "",
                        "base_url": api_openai_base_url or "",
                        "use_proxy": bool(api_openai_use_proxy),
                    })
                    config_manager.set_api_provider_config("dashscope", {
                        "api_key": api_dashscope_key or "",
                        "base_url": api_dashscope_base_url or "",
                        "use_proxy": bool(api_dashscope_use_proxy),
                    })
                    config_manager.set_api_provider_config("ark", {
                        "api_key": api_ark_key or "",
                        "base_url": api_ark_base_url or "",
                        "use_proxy": bool(api_ark_use_proxy),
                    })
                    config_manager.set_api_provider_config("kling", {
                        "base_url": api_kling_base_url or "",
                        "access_key": api_kling_access_key or "",
                        "secret_key": api_kling_secret_key or "",
                        "use_proxy": bool(api_kling_use_proxy),
                    })
                    
                    # Only save to file if LLM config is valid
                    if llm_api_key and llm_base_url and llm_model:
                        config_manager.save()
                        st.success(tr("status.config_saved"))
                        safe_rerun()
                except Exception as e:
                    st.error(f"{tr('status.save_failed')}: {str(e)}")
        
        with col2:
            if st.button(tr("btn.reset_config"), use_container_width=True, key="reset_config_btn"):
                # Reset to default
                from pixelle_video.config.schema import PixelleVideoConfig
                config_manager.config = PixelleVideoConfig()
                config_manager.save()
                st.success(tr("status.config_reset"))
                safe_rerun()
