"""
Exchange Rate Service - 한국수출입은행 API 연동
API 문서: https://www.koreaexim.go.kr/ir/HPHKIR020M01?apino=2&viewtype=C
"""
import httpx
import os
from datetime import datetime, timedelta
from typing import Optional, Dict, List
from sqlalchemy.orm import Session

from ..models.exchange_rate import ExchangeRate, ExchangeRateHistory


# 한국수출입은행 API 설정
KOREAEXIM_API_URL = "https://oapi.koreaexim.go.kr/site/program/financial/exchangeJSON"
KOREAEXIM_API_KEY = os.getenv("KOREAEXIM_API_KEY", "rOzKaATDEinF9luHla1wVTosjWribjKL")

# 지원 통화 목록
SUPPORTED_CURRENCIES = {
    "USD": {"name_ko": "미국 달러", "name_en": "US Dollar", "symbol": "$"},
    "MNT": {"name_ko": "몽골 투그릭", "name_en": "Mongolian Tugrik", "symbol": "₮"},
    "RUB": {"name_ko": "러시아 루블", "name_en": "Russian Ruble", "symbol": "₽"},
    "CNY": {"name_ko": "중국 위안", "name_en": "Chinese Yuan", "symbol": "¥"},
    "JPY": {"name_ko": "일본 엔", "name_en": "Japanese Yen", "symbol": "¥"},
    "EUR": {"name_ko": "유로", "name_en": "Euro", "symbol": "€"},
}

# 기본 환율 (API 실패 시 사용, 2024년 12월 기준)
DEFAULT_RATES = {
    "USD": 1450.0,
    "MNT": 0.42,  # 1 MNT = 0.42 KRW
    "RUB": 14.0,
    "CNY": 198.0,
    "JPY": 9.5,  # 100엔 기준이면 950
    "EUR": 1510.0,
}


async def fetch_rates_from_koreaexim(search_date: Optional[str] = None) -> Optional[List[Dict]]:
    """
    한국수출입은행 API에서 환율 정보 조회

    Args:
        search_date: 조회일자 (YYYYMMDD 형식), 없으면 오늘

    Returns:
        환율 데이터 리스트 또는 None
    """
    if not KOREAEXIM_API_KEY:
        print("Warning: KOREAEXIM_API_KEY not set, using fallback rates")
        return None

    if not search_date:
        search_date = datetime.now().strftime("%Y%m%d")

    try:
        async with httpx.AsyncClient() as client:
            response = await client.get(
                KOREAEXIM_API_URL,
                params={
                    "authkey": KOREAEXIM_API_KEY,
                    "searchdate": search_date,
                    "data": "AP01"  # 환율 데이터
                },
                timeout=15.0
            )

            if response.status_code == 200:
                data = response.json()

                # API 결과 코드 확인
                if isinstance(data, list) and len(data) > 0:
                    return data
                else:
                    print(f"Korea Exim API returned empty data for date {search_date}")
                    # 주말/공휴일이면 이전 영업일 데이터 조회
                    return None

    except Exception as e:
        print(f"Failed to fetch from Korea Exim API: {e}")

    return None


def parse_koreaexim_response(data: List[Dict]) -> Dict[str, Dict]:
    """
    한국수출입은행 API 응답 파싱

    Response format:
    {
        "result": 1,
        "cur_unit": "USD",
        "cur_nm": "미국 달러",
        "ttb": "1,438.71",  # 전신환(송금) 받을때
        "tts": "1,467.28",  # 전신환(송금) 보낼때
        "deal_bas_r": "1,452.99",  # 매매 기준율
        "bkpr": "1,452",  # 장부가격
        ...
    }
    """
    parsed = {}

    for item in data:
        try:
            cur_unit = item.get("cur_unit", "").replace("(100)", "").strip()

            if cur_unit not in SUPPORTED_CURRENCIES:
                continue

            # 쉼표 제거 후 숫자 변환
            deal_base_rate = float(item.get("deal_bas_r", "0").replace(",", ""))
            ttb_rate = float(item.get("ttb", "0").replace(",", ""))
            tts_rate = float(item.get("tts", "0").replace(",", ""))

            # 100엔 단위인 경우 (JPY(100))
            if "(100)" in item.get("cur_unit", ""):
                deal_base_rate /= 100
                ttb_rate /= 100
                tts_rate /= 100

            parsed[cur_unit] = {
                "currency_code": cur_unit,
                "currency_name": item.get("cur_nm", SUPPORTED_CURRENCIES[cur_unit]["name_ko"]),
                "deal_base_rate": deal_base_rate,
                "ttb_rate": ttb_rate,
                "tts_rate": tts_rate,
            }

        except (ValueError, KeyError) as e:
            print(f"Error parsing currency {item.get('cur_unit')}: {e}")
            continue

    return parsed


async def update_exchange_rates(db: Session, force: bool = False) -> Dict:
    """
    환율 정보 업데이트

    Args:
        db: DB 세션
        force: 강제 업데이트 여부

    Returns:
        업데이트 결과
    """
    today = datetime.now().strftime("%Y%m%d")

    # 오늘 이미 업데이트했는지 확인 (force가 아닌 경우)
    if not force:
        existing = db.query(ExchangeRate).filter(
            ExchangeRate.source_date == today
        ).first()

        if existing:
            return {
                "status": "skipped",
                "message": f"Already updated for {today}",
                "source_date": today
            }

    # API 호출 (오늘 데이터 시도)
    api_data = await fetch_rates_from_koreaexim(today)
    source_date = today

    # 오늘 데이터 없으면 어제 시도 (주말/공휴일 대응)
    if not api_data:
        yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y%m%d")
        api_data = await fetch_rates_from_koreaexim(yesterday)
        source_date = yesterday

    # 그래도 없으면 기본값 사용
    if not api_data:
        print("Using fallback rates")
        rates_data = {
            code: {
                "currency_code": code,
                "currency_name": info["name_ko"],
                "deal_base_rate": DEFAULT_RATES.get(code, 1.0),
                "ttb_rate": DEFAULT_RATES.get(code, 1.0) * 0.98,
                "tts_rate": DEFAULT_RATES.get(code, 1.0) * 1.02,
            }
            for code, info in SUPPORTED_CURRENCIES.items()
        }
        source = "fallback"
    else:
        rates_data = parse_koreaexim_response(api_data)
        source = "koreaexim"

    # DB에 저장/업데이트
    updated_currencies = []
    for code, rate_info in rates_data.items():
        existing = db.query(ExchangeRate).filter(
            ExchangeRate.currency_code == code
        ).first()

        if existing:
            # 기존 데이터 업데이트
            old_rate = existing.deal_base_rate
            existing.currency_name = rate_info["currency_name"]
            existing.deal_base_rate = rate_info["deal_base_rate"]
            existing.ttb_rate = rate_info["ttb_rate"]
            existing.tts_rate = rate_info["tts_rate"]
            existing.adjusted_rate = rate_info["deal_base_rate"] * (1 + existing.weight_percent / 100)
            existing.source_date = source_date

            # 변동이 있으면 히스토리 저장
            if old_rate != rate_info["deal_base_rate"]:
                history = ExchangeRateHistory(
                    currency_code=code,
                    deal_base_rate=rate_info["deal_base_rate"],
                    source_date=source_date
                )
                db.add(history)
        else:
            # 신규 데이터 추가
            new_rate = ExchangeRate(
                currency_code=code,
                currency_name=rate_info["currency_name"],
                deal_base_rate=rate_info["deal_base_rate"],
                ttb_rate=rate_info["ttb_rate"],
                tts_rate=rate_info["tts_rate"],
                weight_percent=0.0,
                adjusted_rate=rate_info["deal_base_rate"],
                source_date=source_date,
                is_active=True
            )
            db.add(new_rate)

            # 히스토리 저장
            history = ExchangeRateHistory(
                currency_code=code,
                deal_base_rate=rate_info["deal_base_rate"],
                source_date=source_date
            )
            db.add(history)

        updated_currencies.append(code)

    db.commit()

    return {
        "status": "success",
        "message": f"Updated {len(updated_currencies)} currencies",
        "currencies": updated_currencies,
        "source": source,
        "source_date": source_date
    }


def get_exchange_rate(db: Session, currency_code: str) -> Optional[ExchangeRate]:
    """특정 통화 환율 조회"""
    return db.query(ExchangeRate).filter(
        ExchangeRate.currency_code == currency_code,
        ExchangeRate.is_active == True
    ).first()


def get_all_exchange_rates(db: Session) -> List[ExchangeRate]:
    """모든 환율 조회"""
    return db.query(ExchangeRate).filter(
        ExchangeRate.is_active == True
    ).all()


def convert_krw_to_currency(db: Session, krw_amount: float, currency_code: str) -> Optional[float]:
    """
    KRW를 다른 통화로 변환

    Args:
        db: DB 세션
        krw_amount: 원화 금액
        currency_code: 대상 통화 코드 (USD, MNT, RUB, CNY)

    Returns:
        변환된 금액 또는 None
    """
    rate = get_exchange_rate(db, currency_code)

    if not rate or rate.adjusted_rate <= 0:
        return None

    # KRW / 환율 = 외화
    return krw_amount / rate.adjusted_rate


def convert_currency_to_krw(db: Session, amount: float, currency_code: str) -> Optional[float]:
    """
    다른 통화를 KRW로 변환

    Args:
        db: DB 세션
        amount: 외화 금액
        currency_code: 원화 통화 코드

    Returns:
        KRW 금액 또는 None
    """
    rate = get_exchange_rate(db, currency_code)

    if not rate:
        return None

    # 외화 * 환율 = KRW
    return amount * rate.adjusted_rate
