import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import numpy as np
import seaborn as sns
from typing import Optional
import platform
import os


# 전역 변수: 한글 폰트 속성 (함수들에서 공통 사용)
_korean_font_prop = None


def set_korean_font_global():
    """전역 한글 폰트 설정 함수 (두 함수에서 공통 사용)"""
    global _korean_font_prop
    
    plt.rcParams['axes.unicode_minus'] = False
    
    if platform.system() == 'Windows':
        # Windows 폰트 폴더 경로
        windir = os.environ.get('WINDIR', 'C:\\Windows')
        font_dir = os.path.join(windir, 'Fonts')
        
        # 한글 폰트 파일명 우선순위
        korean_font_files = [
            ('malgun.ttf', 'Malgun Gothic'),          # 맑은 고딕
            ('malgunbd.ttf', 'Malgun Gothic'),        # 맑은 고딕 Bold
            ('NanumGothic.ttf', 'NanumGothic'),       # 나눔고딕
            ('NanumGothicBold.ttf', 'NanumGothic'),   # 나눔고딕 Bold
            ('gulim.ttc', 'Gulim'),                   # 굴림
            ('batang.ttc', 'Batang'),                 # 바탕
            ('dotum.ttc', 'Dotum'),                   # 돋움
        ]
        
        # Windows 폰트 폴더에서 한글 폰트 파일 찾기
        if os.path.exists(font_dir):
            for font_file, font_name in korean_font_files:
                font_path = os.path.join(font_dir, font_file)
                if os.path.exists(font_path):
                    try:
                        # 폰트 직접 로드
                        font_prop = fm.FontProperties(fname=font_path)
                        loaded_font_name = font_prop.get_name()
                        
                        # 전역 변수에 저장 (다른 함수에서 사용)
                        _korean_font_prop = font_prop
                        
                        # 폰트 설정
                        plt.rcParams['font.family'] = loaded_font_name
                        plt.rcParams['font.sans-serif'] = [loaded_font_name] + plt.rcParams['font.sans-serif']
                        
                        # 폰트 캐시에 추가 (선택사항)
                        try:
                            if hasattr(fm.fontManager, 'addfont'):
                                fm.fontManager.addfont(font_path)
                        except:
                            pass
                        
                        return True
                    except Exception:
                        continue
        
        # 대체 방법: font_manager를 통한 폰트 찾기
        try:
            available_fonts = {f.name: f for f in fm.fontManager.ttflist}
            
            korean_font_names = [
                'Malgun Gothic',
                'Microsoft YaHei',
                'NanumGothic',
                'Nanum Gothic',
                'Gulim',
                'Batang',
                'Dotum',
            ]
            
            for font_name in korean_font_names:
                if font_name in available_fonts:
                    font = available_fonts[font_name]
                    if os.path.exists(font.fname):
                        try:
                            plt.rcParams['font.family'] = font_name
                            plt.rcParams['font.sans-serif'] = [font_name] + plt.rcParams['font.sans-serif']
                            return True
                        except:
                            continue
        except:
            pass
        
        # 최종 대체: 맑은 고딕 직접 설정 시도
        try:
            plt.rcParams['font.family'] = 'Malgun Gothic'
            plt.rcParams['font.sans-serif'] = ['Malgun Gothic', 'DejaVu Sans']
        except:
            plt.rcParams['font.family'] = 'DejaVu Sans'
    else:
        # Linux/Mac 환경
        plt.rcParams['font.family'] = 'DejaVu Sans'


def plot_risk_comparison(rr_result_df, figsize=(14, 8), 
                         save_path: Optional[str] = None,
                         dpi=300, style='whitegrid'):
    """
    RR_calculator 결과를 시각적으로 비교하는 함수.
    위험도와 상대위험도를 깔끔하고 보기 좋은 bar chart로 표현.
    
    디자인 특징:
    - 깔끔한 색상 팔레트
    - 명확한 레이블과 범례
    - 프레젠테이션용 고해상도
    - 한글 폰트 지원
    
    Parameters:
    -----------
    rr_result_df : pd.DataFrame
        RR_calculator 함수의 반환값
        컬럼: '지표', 'A발생수', 'A모수', 'A위험도', 'B발생수', 'B모수', 'B위험도', 
              '차이', '상대위험도', '변화율'
    figsize : tuple, optional
        그래프 크기 (가로, 세로). 기본값: (14, 8)
    save_path : str, optional
        저장 경로. None이면 표시만 함. 기본값: None
    dpi : int, optional
        저장 해상도. 기본값: 300
    style : str, optional
        seaborn 스타일. 기본값: 'whitegrid'
    
    Returns:
    --------
    matplotlib.figure.Figure
        생성된 figure 객체
    """
    # 스타일 설정
    sns.set_style(style)
    
    # 한글 폰트 설정
    set_korean_font_global()
    
    # 데이터 준비
    df = rr_result_df.copy()
    
    # 상대위험도가 'Inf' 문자열인 경우 처리
    df['상대위험도_수치'] = df['상대위험도'].apply(
        lambda x: np.nan if isinstance(x, str) and x == 'Inf' else float(x)
    )
    
    # 지표명 정리 (영어를 한글로 변환)
    indicator_names = {
        'cancer': '암',
        'brain': '뇌혈관질환',
        'heart': '심장질환',
        'disease_sur': '질병수술',
        'injury_sur': '외상수술',
        'disease_hos': '질병입원',
        'injury_hos': '외상입원'
    }
    
    df['지표_한글'] = df['지표'].map(indicator_names).fillna(df['지표'])
    
    # Figure 생성
    fig, axes = plt.subplots(1, 2, figsize=figsize)
    
    # 한글 폰트 속성 가져오기
    font_prop = _korean_font_prop if _korean_font_prop else None
    
    if font_prop:
        fig.suptitle('위험도 비교 분석', fontsize=18, fontweight='bold', y=1.02, fontproperties=font_prop)
    else:
        fig.suptitle('위험도 비교 분석', fontsize=18, fontweight='bold', y=1.02)
    
    # 색상 팔레트 설정
    colors = {
        '그룹A': '#4A90E2',  # 파란색
        '그룹B': '#E24A4A',  # 빨간색
        '상대위험도': '#50C878'  # 초록색
    }
    
    # ========================================================================
    # 1. 위험도 비교 (그룹 A vs 그룹 B)
    # ========================================================================
    ax1 = axes[0]
    
    x_pos = np.arange(len(df))
    width = 0.35
    
    bars1 = ax1.bar(x_pos - width/2, df['A위험도'], width, 
                    label='그룹 A', color=colors['그룹A'], alpha=0.8, edgecolor='white', linewidth=1.5)
    bars2 = ax1.bar(x_pos + width/2, df['B위험도'], width, 
                    label='그룹 B', color=colors['그룹B'], alpha=0.8, edgecolor='white', linewidth=1.5)
    
    if font_prop:
        ax1.set_xlabel('지표', fontsize=12, fontweight='bold', fontproperties=font_prop)
        ax1.set_ylabel('위험도', fontsize=12, fontweight='bold', fontproperties=font_prop)
        ax1.set_title('그룹별 위험도 비교', fontsize=14, fontweight='bold', pad=20, fontproperties=font_prop)
        ax1.set_xticklabels(df['지표_한글'], rotation=45, ha='right', fontsize=10, fontproperties=font_prop)
    else:
        ax1.set_xlabel('지표', fontsize=12, fontweight='bold')
        ax1.set_ylabel('위험도', fontsize=12, fontweight='bold')
        ax1.set_title('그룹별 위험도 비교', fontsize=14, fontweight='bold', pad=20)
        ax1.set_xticklabels(df['지표_한글'], rotation=45, ha='right', fontsize=10)
    ax1.set_xticks(x_pos)
    ax1.legend(fontsize=11, loc='upper left', framealpha=0.9)
    ax1.grid(axis='y', alpha=0.3, linestyle='--')
    ax1.set_axisbelow(True)
    
    # 값 레이블 추가 (위험도가 너무 작으면 생략)
    for bars in [bars1, bars2]:
        for bar in bars:
            height = bar.get_height()
            if height > 0.001:  # 0.001 이상인 경우만 표시
                ax1.text(bar.get_x() + bar.get_width()/2., height,
                        f'{height:.3f}',
                        ha='center', va='bottom', fontsize=8)
    
    # ========================================================================
    # 2. 상대위험도 (B/A)
    # ========================================================================
    ax2 = axes[1]
    
    # 상대위험도가 유효한 경우만 시각화
    valid_mask = df['상대위험도_수치'].notna()
    valid_df = df[valid_mask].copy()
    invalid_df = df[~valid_mask].copy()
    
    if len(valid_df) > 0:
        # 기준선 (상대위험도 = 1.0)
        ax2.axhline(y=1.0, color='gray', linestyle='--', linewidth=2, alpha=0.5, label='기준선 (1.0)')
        
        # 상대위험도 바 차트
        colors_bars = [colors['상대위험도'] if x >= 1.0 else '#FF6B6B' for x in valid_df['상대위험도_수치']]
        bars3 = ax2.bar(range(len(valid_df)), valid_df['상대위험도_수치'], 
                       color=colors_bars, alpha=0.8, edgecolor='white', linewidth=1.5)
        
        # y축 범위 조정: 기준선 1.0이 차트의 2/3 지점에 오도록 설정
        data_max = valid_df['상대위험도_수치'].max()
        data_min = max(0, valid_df['상대위험도_수치'].min() * 0.9)  # 최소값은 0 이상
        
        # 기준선 1.0이 2/3 지점에 오도록 y_max 계산
        # (1.0 - y_min) / (y_max - y_min) = 2/3
        # 3 * (1.0 - y_min) = 2 * (y_max - y_min)
        # y_max = (3 - y_min) / 2
        y_min = data_min
        y_max_for_baseline = (3.0 - y_min) / 2.0
        
        # 데이터가 잘리지 않도록 조정
        # 데이터 최대값이 계산된 y_max보다 크면, 데이터를 포함하면서도 기준선을 가능한 한 2/3에 가깝게
        if data_max * 1.1 > y_max_for_baseline:
            # 데이터를 포함하되, 기준선이 2/3에 가깝도록 조정
            y_max_final = max(data_max * 1.1, y_max_for_baseline)
        else:
            y_max_final = y_max_for_baseline
        
        ax2.set_ylim(bottom=y_min, top=y_max_final)
        
        # 값 레이블 추가
        for i, (bar, val) in enumerate(zip(bars3, valid_df['상대위험도_수치'])):
            height = bar.get_height()
            ax2.text(bar.get_x() + bar.get_width()/2., height,
                    f'{val:.2f}',
                    ha='center', va='bottom' if height >= 1.0 else 'top', 
                    fontsize=9, fontweight='bold')
        
        ax2.set_xticks(range(len(valid_df)))
        if font_prop:
            ax2.set_xticklabels(valid_df['지표_한글'], rotation=45, ha='right', fontsize=10, fontproperties=font_prop)
        else:
            ax2.set_xticklabels(valid_df['지표_한글'], rotation=45, ha='right', fontsize=10)
    
    if font_prop:
        ax2.set_xlabel('지표', fontsize=12, fontweight='bold', fontproperties=font_prop)
        ax2.set_ylabel('상대위험도 (B/A)', fontsize=12, fontweight='bold', fontproperties=font_prop)
        ax2.set_title('상대위험도 (그룹 B / 그룹 A)', fontsize=14, fontweight='bold', pad=20, fontproperties=font_prop)
    else:
        ax2.set_xlabel('지표', fontsize=12, fontweight='bold')
        ax2.set_ylabel('상대위험도 (B/A)', fontsize=12, fontweight='bold')
        ax2.set_title('상대위험도 (그룹 B / 그룹 A)', fontsize=14, fontweight='bold', pad=20)
    ax2.legend(fontsize=11, loc='upper left', framealpha=0.9)
    ax2.grid(axis='y', alpha=0.3, linestyle='--')
    ax2.set_axisbelow(True)
    
    # Inf 값이 있는 경우 범례에 표시
    if len(invalid_df) > 0:
        ax2.text(0.02, 0.98, f"* {len(invalid_df)}개 지표는 상대위험도가 무한대(Inf)입니다.",
                transform=ax2.transAxes, fontsize=9, verticalalignment='top',
                bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))
    
    # 레이아웃 조정
    plt.tight_layout()
    
    # 저장 또는 표시
    if save_path:
        plt.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor='white')
        print(f"그래프가 저장되었습니다: {save_path}")
    else:
        plt.show()
    
    return fig


def plot_risk_comparison_vertical(rr_result_df, figsize=(12, 10), 
                                  save_path: Optional[str] = None,
                                  dpi=300, style='whitegrid'):
    """
    RR_calculator 결과를 세로로 배치한 버전 (프레젠테이션용).
    
    Parameters:
    -----------
    rr_result_df : pd.DataFrame
        RR_calculator 함수의 반환값
    figsize : tuple, optional
        그래프 크기 (가로, 세로). 기본값: (12, 10)
    save_path : str, optional
        저장 경로. None이면 표시만 함. 기본값: None
    dpi : int, optional
        저장 해상도. 기본값: 300
    style : str, optional
        seaborn 스타일. 기본값: 'whitegrid'
    
    Returns:
    --------
    matplotlib.figure.Figure
        생성된 figure 객체
    """
    # 스타일 설정
    sns.set_style(style)
    
    # 한글 폰트 설정
    set_korean_font_global()
    
    # 데이터 준비
    df = rr_result_df.copy()
    
    # 상대위험도가 'Inf' 문자열인 경우 처리
    df['상대위험도_수치'] = df['상대위험도'].apply(
        lambda x: np.nan if isinstance(x, str) and x == 'Inf' else float(x)
    )
    
    # 지표명 정리
    indicator_names = {
        'cancer': '암',
        'brain': '뇌혈관질환',
        'heart': '심장질환',
        'disease_sur': '질병수술',
        'injury_sur': '외상수술',
        'disease_hos': '질병입원',
        'injury_hos': '외상입원'
    }
    
    df['지표_한글'] = df['지표'].map(indicator_names).fillna(df['지표'])
    
    # Figure 생성
    fig, axes = plt.subplots(2, 1, figsize=figsize)
    
    # 한글 폰트 속성 가져오기
    font_prop = _korean_font_prop if _korean_font_prop else None
    
    if font_prop:
        fig.suptitle('위험도 비교 분석', fontsize=18, fontweight='bold', y=0.98, fontproperties=font_prop)
    else:
        fig.suptitle('위험도 비교 분석', fontsize=18, fontweight='bold', y=0.98)
    
    # 색상 팔레트 설정
    colors = {
        '그룹A': '#4A90E2',
        '그룹B': '#E24A4A',
        '상대위험도': '#50C878'
    }
    
    # 위험도 비교
    ax1 = axes[0]
    x_pos = np.arange(len(df))
    width = 0.35
    
    bars1 = ax1.bar(x_pos - width/2, df['A위험도'], width, 
                    label='그룹 A', color=colors['그룹A'], alpha=0.8, edgecolor='white', linewidth=1.5)
    bars2 = ax1.bar(x_pos + width/2, df['B위험도'], width, 
                    label='그룹 B', color=colors['그룹B'], alpha=0.8, edgecolor='white', linewidth=1.5)
    
    if font_prop:
        ax1.set_xlabel('지표', fontsize=12, fontweight='bold', fontproperties=font_prop)
        ax1.set_ylabel('위험도', fontsize=12, fontweight='bold', fontproperties=font_prop)
        ax1.set_title('그룹별 위험도 비교', fontsize=14, fontweight='bold', pad=15, fontproperties=font_prop)
        ax1.set_xticklabels(df['지표_한글'], rotation=45, ha='right', fontsize=10, fontproperties=font_prop)
    else:
        ax1.set_xlabel('지표', fontsize=12, fontweight='bold')
        ax1.set_ylabel('위험도', fontsize=12, fontweight='bold')
        ax1.set_title('그룹별 위험도 비교', fontsize=14, fontweight='bold', pad=15)
        ax1.set_xticklabels(df['지표_한글'], rotation=45, ha='right', fontsize=10)
    ax1.set_xticks(x_pos)
    ax1.legend(fontsize=11, loc='upper left', framealpha=0.9)
    ax1.grid(axis='y', alpha=0.3, linestyle='--')
    ax1.set_axisbelow(True)
    
    # 상대위험도
    ax2 = axes[1]
    valid_mask = df['상대위험도_수치'].notna()
    valid_df = df[valid_mask].copy()
    
    if len(valid_df) > 0:
        ax2.axhline(y=1.0, color='gray', linestyle='--', linewidth=2, alpha=0.5, label='기준선 (1.0)')
        colors_bars = [colors['상대위험도'] if x >= 1.0 else '#FF6B6B' for x in valid_df['상대위험도_수치']]
        bars3 = ax2.bar(range(len(valid_df)), valid_df['상대위험도_수치'], 
                       color=colors_bars, alpha=0.8, edgecolor='white', linewidth=1.5)
        
        # y축 범위 조정: 기준선 1.0이 차트의 2/3 지점에 오도록 설정
        data_max = valid_df['상대위험도_수치'].max()
        data_min = max(0, valid_df['상대위험도_수치'].min() * 0.9)  # 최소값은 0 이상
        
        # 기준선 1.0이 2/3 지점에 오도록 y_max 계산
        # (1.0 - y_min) / (y_max - y_min) = 2/3
        # 3 * (1.0 - y_min) = 2 * (y_max - y_min)
        # y_max = (3 - y_min) / 2
        y_min = data_min
        y_max_for_baseline = (3.0 - y_min) / 2.0
        
        # 데이터가 잘리지 않도록 조정
        # 데이터 최대값이 계산된 y_max보다 크면, 데이터를 포함하면서도 기준선을 가능한 한 2/3에 가깝게
        if data_max * 1.1 > y_max_for_baseline:
            # 데이터를 포함하되, 기준선이 2/3에 가깝도록 조정
            y_max_final = max(data_max * 1.1, y_max_for_baseline)
        else:
            y_max_final = y_max_for_baseline
        
        ax2.set_ylim(bottom=y_min, top=y_max_final)
        
        for i, (bar, val) in enumerate(zip(bars3, valid_df['상대위험도_수치'])):
            height = bar.get_height()
            ax2.text(bar.get_x() + bar.get_width()/2., height,
                    f'{val:.2f}',
                    ha='center', va='bottom' if height >= 1.0 else 'top', 
                    fontsize=9, fontweight='bold')
        
        ax2.set_xticks(range(len(valid_df)))
        if font_prop:
            ax2.set_xticklabels(valid_df['지표_한글'], rotation=45, ha='right', fontsize=10, fontproperties=font_prop)
        else:
            ax2.set_xticklabels(valid_df['지표_한글'], rotation=45, ha='right', fontsize=10)
    
    if font_prop:
        ax2.set_xlabel('지표', fontsize=12, fontweight='bold', fontproperties=font_prop)
        ax2.set_ylabel('상대위험도 (B/A)', fontsize=12, fontweight='bold', fontproperties=font_prop)
        ax2.set_title('상대위험도 (그룹 B / 그룹 A)', fontsize=14, fontweight='bold', pad=15, fontproperties=font_prop)
    else:
        ax2.set_xlabel('지표', fontsize=12, fontweight='bold')
        ax2.set_ylabel('상대위험도 (B/A)', fontsize=12, fontweight='bold')
        ax2.set_title('상대위험도 (그룹 B / 그룹 A)', fontsize=14, fontweight='bold', pad=15)
    ax2.legend(fontsize=11, loc='upper left', framealpha=0.9)
    ax2.grid(axis='y', alpha=0.3, linestyle='--')
    ax2.set_axisbelow(True)
    
    plt.tight_layout()
    
    if save_path:
        plt.savefig(save_path, dpi=dpi, bbox_inches='tight', facecolor='white')
        print(f"그래프가 저장되었습니다: {save_path}")
    else:
        plt.show()
    
    return fig
