"""
月次レポート - PDF用グラフ生成（matplotlib）
"""
import os
import base64
from io import BytesIO

import matplotlib
matplotlib.use('Agg')  # GUI不要のバックエンド

import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import numpy as np

# 日本語フォント設定
# Ubuntu: fonts-noto-cjk をインストール済みの場合
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['Noto Sans CJK JP', 'Noto Sans CJK', 'DejaVu Sans', 'Arial']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.size'] = 10

# matplotlibのフォントキャッシュをリビルド（初回のみ必要な場合あり）
try:
    fm._load_fontmanager(try_read_cache=False)
except:
    pass

# 共通色定義（matplotlib用のRGBAタプル形式）
COLORS = {
    'primary': '#2196F3',
    'primary_light': (0.13, 0.59, 0.95, 0.6),
    'success': '#4CAF50',
    'success_light': (0.30, 0.69, 0.31, 0.6),
    'danger': '#F44336',
    'danger_light': (0.96, 0.26, 0.21, 0.6),
    'warning': '#FF9800',
    'warning_light': (1.0, 0.60, 0.0, 0.6),
    'gray': '#9E9E9E',
    'gray_light': (0.62, 0.62, 0.62, 0.6),
    'teal': (0.29, 0.75, 0.75, 0.6),
    'teal_border': (0.29, 0.75, 0.75, 1.0),
    'red': (1.0, 0.39, 0.52, 0.6),
    'red_border': (1.0, 0.39, 0.52, 1.0),
    'blue': (0.21, 0.64, 0.92, 1.0),
}


def _fig_to_base64(fig) -> str:
    """matplotlibのfigureをbase64エンコードされた画像に変換"""
    buf = BytesIO()
    fig.savefig(buf, format='png', dpi=150, bbox_inches='tight',
                facecolor='white', edgecolor='none')
    buf.seek(0)
    img_base64 = base64.b64encode(buf.read()).decode('utf-8')
    buf.close()
    plt.close(fig)
    return f"data:image/png;base64,{img_base64}"


def generate_daily_chart(daily_stats: list) -> str:
    """
    日別回答統計グラフ（棒グラフ + 折れ線）
    """
    if not daily_stats:
        return None

    dates = [d.get('date', '')[-5:] for d in daily_stats]  # MM-DD形式
    total = [int(d.get('total_conversations', 0)) for d in daily_stats]
    answered = [int(d.get('answered_count', 0)) for d in daily_stats]
    unanswered = [int(d.get('unanswered_count', 0)) for d in daily_stats]

    fig, ax = plt.subplots(figsize=(10, 4))

    x = np.arange(len(dates))
    width = 0.35

    ax.bar(x - width/2, answered, width, label='回答できた', color=COLORS['teal'])
    ax.bar(x + width/2, unanswered, width, label='回答できなかった', color=COLORS['red'])

    if len(x) >= 3:
        from scipy.interpolate import PchipInterpolator
        x_smooth = np.linspace(x.min(), x.max(), len(x) * 10)
        pchip = PchipInterpolator(x, total)
        ax.plot(x_smooth, pchip(x_smooth), '-', label='総会話数', color=COLORS['blue'], linewidth=2)
        ax.plot(x, total, 'o', color=COLORS['blue'], markersize=4)
    else:
        ax.plot(x, total, 'o-', label='総会話数', color=COLORS['blue'], linewidth=2)

    ax.set_xlabel('日付')
    ax.set_ylabel('件数')
    ax.set_title('日別回答統計')
    ax.set_xticks(x)
    ax.set_xticklabels(dates, rotation=45, ha='right')
    ax.legend(loc='upper left')
    ax.grid(axis='y', alpha=0.3)

    plt.tight_layout()
    return _fig_to_base64(fig)


def generate_comparison_chart(comparison: dict) -> str:
    """
    前月比較グラフ
    """
    if not comparison:
        return None

    prev = comparison.get('previous', {})
    curr = comparison.get('current', {})

    labels = ['総会話数', '回答できた', '回答できなかった', 'いいね', 'よくない']
    prev_data = [
        prev.get('total_conversations', 0),
        prev.get('answered_count', 0),
        prev.get('unanswered_count', 0),
        prev.get('likes_count', 0),
        prev.get('dislikes_count', 0)
    ]
    curr_data = [
        curr.get('total_conversations', 0),
        curr.get('answered_count', 0),
        curr.get('unanswered_count', 0),
        curr.get('likes_count', 0),
        curr.get('dislikes_count', 0)
    ]

    fig, ax = plt.subplots(figsize=(8, 4))

    x = np.arange(len(labels))
    width = 0.35

    ax.bar(x - width/2, prev_data, width, label='前月', color=COLORS['gray_light'])
    ax.bar(x + width/2, curr_data, width, label='当月', color=COLORS['primary_light'])

    ax.set_ylabel('件数')
    ax.set_title('前月比較')
    ax.set_xticks(x)
    ax.set_xticklabels(labels)
    ax.legend()
    ax.grid(axis='y', alpha=0.3)

    plt.tight_layout()
    return _fig_to_base64(fig)


def generate_hourly_chart(hourly_stats: list) -> str:
    """
    時間帯別分布グラフ
    """
    if not hourly_stats:
        return None

    # 0-23時のデータを準備
    hour_data = {h: 0 for h in range(24)}
    for item in hourly_stats:
        hour = item.get('hour', 0)
        count = item.get('total_conversations', 0)
        hour_data[hour] = count

    hours = list(range(24))
    counts = [hour_data[h] for h in hours]

    fig, ax = plt.subplots(figsize=(10, 4))

    ax.bar(hours, counts, color=COLORS['primary_light'], edgecolor=COLORS['primary'])

    ax.set_xlabel('時間帯')
    ax.set_ylabel('質問数')
    ax.set_title('時間帯別質問数')
    ax.set_xticks(hours)
    ax.set_xticklabels([f'{h}時' for h in hours], rotation=45, ha='right')
    ax.grid(axis='y', alpha=0.3)

    plt.tight_layout()
    return _fig_to_base64(fig)


def generate_day_of_week_chart(dow_stats: list) -> str:
    """
    曜日別グラフ
    """
    if not dow_stats:
        return None

    day_names = ['月', '火', '水', '木', '金', '土', '日']
    day_data = {i: 0 for i in range(7)}

    for item in dow_stats:
        dow = item.get('day_of_week', 0)
        count = item.get('total_conversations', 0)
        day_data[dow] = count

    counts = [day_data[i] for i in range(7)]
    colors = [COLORS['warning_light'] if i >= 5 else COLORS['primary_light'] for i in range(7)]

    fig, ax = plt.subplots(figsize=(6, 4))

    ax.bar(day_names, counts, color=colors, edgecolor=COLORS['primary'])

    ax.set_ylabel('質問数')
    ax.set_title('曜日別質問数')
    ax.grid(axis='y', alpha=0.3)

    plt.tight_layout()
    return _fig_to_base64(fig)


def generate_resolution_pie_chart(summary: dict) -> str:
    """
    回答可否円グラフ
    """
    if not summary:
        return None

    answered = summary.get('answered_count', 0)
    unanswered = summary.get('unanswered_count', 0)

    if answered == 0 and unanswered == 0:
        return None

    fig, ax = plt.subplots(figsize=(5, 4))

    sizes = [answered, unanswered]
    labels = ['回答できた', '回答できなかった']
    colors = [COLORS['success'], COLORS['danger']]

    ax.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%',
           startangle=90, pctdistance=0.75, wedgeprops=dict(width=0.5))
    ax.set_title('回答可否')

    plt.tight_layout()
    return _fig_to_base64(fig)


def generate_keywords_chart(keywords: list, title: str = '頻出キーワード TOP10') -> str:
    """
    キーワード横棒グラフ
    """
    if not keywords:
        return None

    # 上位10件
    top10 = keywords[:10]

    # データ形式の判定: [[keyword, count], ...] or [{'keyword': ..., 'count': ...}, ...]
    if isinstance(top10[0], (list, tuple)):
        labels = [k[0] for k in top10]
        counts = [k[1] for k in top10]
    else:
        labels = [k.get('keyword', '') for k in top10]
        counts = [k.get('count', 0) for k in top10]

    fig, ax = plt.subplots(figsize=(8, 4))

    y = np.arange(len(labels))
    ax.barh(y, counts, color=COLORS['primary_light'], edgecolor=COLORS['primary'])

    ax.set_yticks(y)
    ax.set_yticklabels(labels)
    ax.set_xlabel('出現回数')
    ax.set_title(title)
    ax.invert_yaxis()
    ax.grid(axis='x', alpha=0.3)

    plt.tight_layout()
    return _fig_to_base64(fig)


def generate_category_ranking_chart(category_ranking: list) -> str:
    """
    カテゴリ別問い合わせランキング
    """
    if not category_ranking:
        return None

    # 上位10件
    top10 = category_ranking[:10]

    # データ形式: [(id, category_name, count), ...]
    labels = [item[1] for item in top10]
    counts = [item[2] for item in top10]

    fig, ax = plt.subplots(figsize=(8, 4))

    y = np.arange(len(labels))
    ax.barh(y, counts, color=COLORS['primary_light'], edgecolor=COLORS['primary'])

    ax.set_yticks(y)
    ax.set_yticklabels(labels)
    ax.set_xlabel('参照回数')
    ax.set_title('カテゴリ別問い合わせランキング TOP10')
    ax.invert_yaxis()
    ax.grid(axis='x', alpha=0.3)

    plt.tight_layout()
    return _fig_to_base64(fig)


def generate_all_charts(data: dict) -> dict:
    """
    全グラフを生成してbase64画像の辞書を返す
    """
    charts = {}

    # 日別統計
    if data.get('daily_stats'):
        charts['daily'] = generate_daily_chart(data['daily_stats'])

    # 前月比較
    if data.get('comparison'):
        charts['comparison'] = generate_comparison_chart(data['comparison'])

    # 時間帯別
    if data.get('hourly_stats'):
        charts['hourly'] = generate_hourly_chart(data['hourly_stats'])

    # 曜日別
    if data.get('day_of_week_stats'):
        charts['day_of_week'] = generate_day_of_week_chart(data['day_of_week_stats'])

    # 回答可否
    if data.get('summary'):
        charts['resolution_pie'] = generate_resolution_pie_chart(data['summary'])

    # キーワード
    if data.get('keywords'):
        charts['keywords'] = generate_keywords_chart(
            data['keywords'], '頻出キーワード TOP10')

    # 未解決キーワード
    if data.get('unresolved_keywords'):
        charts['unresolved_keywords'] = generate_keywords_chart(
            data['unresolved_keywords'], '未解決キーワード TOP10')

    # カテゴリ別ランキング
    if data.get('category_usage_ranking'):
        charts['category_ranking'] = generate_category_ranking_chart(
            data['category_usage_ranking'])

    return charts
