"""CLI for initializing Gar configuration interactively.
Gac의 init_cli.py 스타일을 참고하여 간단한 초기 설정 제공.
"""

from pathlib import Path
from typing import cast

import click
import questionary
from dotenv import dotenv_values, set_key

from interface.llm.client import get_default_model, list_available_models

# Gar 설정은 프로젝트 루트의 .env 파일만을 기준으로 관리한다.
GAR_ENV_PATH = Path(".env")


def _prompt_required_text(prompt: str) -> str | None:
    """Prompt until a non-empty string is provided or the user cancels"""
    while True:
        response = questionary.text(prompt).ask()
        if response is None:
            return None
        value = response.strip()
        if value:
            return cast(str, value)
        click.echo("값이 필요합니다. 다시 입력해주세요.")


def _load_existing_env() -> dict[str, str]:
    """Ensure the project .env file exists and return its current values.

    새로 생성되는 경우 기본값도 함께 기록한다.
    """
    existing_env: dict[str, str] = {}
    if GAR_ENV_PATH.exists():
        click.echo(f".env 파일이 이미 존재합니다: {GAR_ENV_PATH}. 값이 업데이트됩니다.")
        existing_env = {
            k: v for k, v in dotenv_values(str(GAR_ENV_PATH)).items() if v is not None
        }
    else:
        GAR_ENV_PATH.touch()
        click.echo(f".env 파일을 생성했습니다: {GAR_ENV_PATH}.")
        # 기본 값 설정
        set_key(str(GAR_ENV_PATH), "GAR_TEMPERATURE", "0.2")
        set_key(str(GAR_ENV_PATH), "GAR_MAX_OUTPUT_TOKENS", "2048")
        set_key(str(GAR_ENV_PATH), "GAR_MAX_RETRIES", "3")
        existing_env = {
            "GAR_TEMPERATURE": "0.2",
            "GAR_MAX_OUTPUT_TOKENS": "2048",
            "GAR_MAX_RETRIES": "3",
        }
    return existing_env


def _configure_llm_server(existing_env: dict[str, str]) -> str:
    """LLM 서버 URL을 설정한다."""
    existing_url = existing_env.get("GAR_LLM_BASE_URL", "")

    click.echo("\n=== LLM 서버 설정 ===")
    
    url = questionary.text(
        "LLM 서버 Base URL:",
        default=existing_url,
    ).ask()

    # 입력값 검증 - 반드시 입력해야 함
    while url is None or not url.strip():
        click.echo("⚠️  LLM 서버 주소는 필수입니다. 다시 입력해주세요.")
        url = questionary.text(
            "LLM 서버 Base URL:",
            default="",
        ).ask()
        if url is None:
            raise KeyboardInterrupt("설정이 취소되었습니다.")
    
    url = url.strip()
    set_key(str(GAR_ENV_PATH), "GAR_LLM_BASE_URL", url)
    click.echo(f"✅ GAR_LLM_BASE_URL={url}")
    return url


def _configure_model(base_url: str, existing_env: dict[str, str]) -> bool:
    """모델 설정"""
    click.echo("\n=== 모델 설정 ===")

    # 서버에서 사용 가능한 모델 목록 조회 시도
    available_models: list[str] = []
    try:
        available_models = list_available_models(base_url)
        if available_models:
            click.echo(f"사용 가능한 모델을 찾았습니다: {len(available_models)}개")
    except Exception as e:
        click.echo(f"⚠️  서버에서 모델 목록을 가져올 수 없습니다: {e}")
        click.echo("   직접 모델 이름을 입력하세요.")

    # 모델 선택 방식 선택
    if available_models:
        choices = ["서버에서 자동 선택 (첫 번째 모델)", "모델 목록에서 선택", "직접 입력"]
        choice = questionary.select(
            "모델을 어떻게 선택하시겠습니까?",
            choices=choices,
            use_shortcuts=True,
        ).ask()

        if choice is None:
            click.echo("모델 설정이 취소되었습니다.")
            return False

        if choice.startswith("서버에서 자동"):
            # 모델을 설정하지 않으면 자동으로 선택됨
            click.echo("✅ 모델은 실행 시 자동으로 선택됩니다.")
            return True
        elif choice.startswith("모델 목록"):
            # 모델 목록에서 선택
            selected = questionary.select(
                "사용할 모델을 선택하세요:",
                choices=available_models,
                use_shortcuts=True,
            ).ask()
            if selected is None:
                click.echo("모델 선택이 취소되었습니다.")
                return False
            model = selected
        else:
            # 직접 입력
            model = _prompt_required_text("모델 이름을 입력하세요:")
            if model is None:
                click.echo("모델 입력이 취소되었습니다.")
                return False
    else:
        # 모델 목록을 가져올 수 없으면 직접 입력
        existing_model = existing_env.get("GAR_MODEL", "")
        model = questionary.text(
            "모델 이름을 입력하세요:",
            default=existing_model,
        ).ask()
        if model is None or not model.strip():
            click.echo("모델 입력이 취소되었습니다.")
            return False
        model = model.strip()

    set_key(str(GAR_ENV_PATH), "GAR_MODEL", model)
    click.echo(f"✅ GAR_MODEL={model}")
    return True


def _configure_language(existing_env: dict[str, str]) -> None:
    """언어 설정"""
    click.echo("\n=== 언어 설정 ===")
    existing_lang = existing_env.get("GAR_LANGUAGE", "Korean")
    language = questionary.text(
        "출력 언어:",
        default=existing_lang,
    ).ask()

    if language is None or not language.strip():
        language = "Korean"
    else:
        language = language.strip()

    set_key(str(GAR_ENV_PATH), "GAR_LANGUAGE", language)
    click.echo(f"✅ GAR_LANGUAGE={language}")


def _run_init() -> None:
    """초기 설정의 실제 로직 (click 없이 호출 가능)"""
    click.echo("Gar 초기 설정에 오신 것을 환영합니다!\n")

    existing_env = _load_existing_env()

    # LLM 서버 URL 설정
    base_url = _configure_llm_server(existing_env)

    # 모델 설정
    if not _configure_model(base_url, existing_env):
        click.echo("모델 설정이 취소되었습니다. 종료합니다.")
        return

    # 언어 설정
    _configure_language(existing_env)

    click.echo("\n✅ Gar 환경 설정이 완료되었습니다! 🎉")
    click.echo("설정이 저장된 위치:")
    click.echo(f"  {GAR_ENV_PATH.resolve()}")
    click.echo("\n이제 'gar' 명령어를 실행하여 코드 리뷰를 시작할 수 있습니다.")
    click.echo("'gar --help'로 사용 가능한 옵션을 확인하세요.")


@click.command()
def init() -> None:
    """현재 디렉터리의 .env를 인터랙티브하게 설정합니다."""
    _run_init()
