"""
月次レポート生成サービス - グラフ描画
"""
import os
import tempfile
import matplotlib
matplotlib.use('Agg')  # バックエンドをAggに設定（GUIなし）

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

# 日本語フォント設定
def setup_japanese_font():
    """日本語フォントを設定（フォントファイルを直接指定）"""
    # Windows/Mac/Linuxで利用可能なフォントファイルを探す
    font_paths = [
        # Windows
        'C:/Windows/Fonts/meiryo.ttc',
        'C:/Windows/Fonts/msgothic.ttc',
        'C:/Windows/Fonts/YuGothR.ttc',
        'C:/Windows/Fonts/MSGOTHIC.TTC',
        # Mac
        '/System/Library/Fonts/ヒラギノ角ゴシック W3.ttc',
        '/Library/Fonts/Arial Unicode.ttf',
        # Linux
        '/usr/share/fonts/truetype/fonts-japanese-gothic.ttf',
        '/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc',
    ]

    for font_path in font_paths:
        if os.path.exists(font_path):
            try:
                # フォントをmatplotlibに追加
                fm.fontManager.addfont(font_path)
                font_prop = fm.FontProperties(fname=font_path)
                font_name = font_prop.get_name()
                plt.rcParams['font.family'] = font_name
                plt.rcParams['font.sans-serif'] = [font_name, 'DejaVu Sans']
                return font_name
            except Exception:
                continue

    # 見つからない場合はデフォルトを使用
    return None


class ChartGenerator:
    """グラフ生成クラス"""

    def __init__(self, output_dir: str = None):
        self.output_dir = output_dir or tempfile.mkdtemp()
        self._chart_count = 0
        self.font = setup_japanese_font()

        # スタイル設定
        plt.style.use('seaborn-v0_8-whitegrid')
        plt.rcParams['axes.unicode_minus'] = False
        plt.rcParams['figure.dpi'] = 150

        # 日本語フォントが見つかった場合は再設定
        if self.font:
            plt.rcParams['font.family'] = self.font
            plt.rcParams['font.sans-serif'] = [self.font, 'DejaVu Sans']

    def _get_chart_path(self, name: str) -> str:
        """一意なチャートファイルパスを生成"""
        self._chart_count += 1
        return os.path.join(self.output_dir, f"{self._chart_count:02d}_{name}.png")

    def generate_daily_chart(self, data: list) -> str:
        """日別会話数グラフ"""
        if not data:
            return self._generate_empty_chart("日別会話数", "データがありません")

        dates = [d['date'] for d in data]
        total = [d['total_conversations'] for d in data]
        answered = [d['answered_count'] for d in data]
        unanswered = [d['unanswered_count'] for d in data]

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

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

        ax.bar(x, answered, width, label='回答できた', color='#4CAF50', alpha=0.8)
        ax.bar(x, unanswered, width, bottom=answered, label='回答できなかった', color='#F44336', alpha=0.8)

        # 総数の折れ線
        ax.plot(x, total, 'o-', color='#333333', linewidth=2, markersize=4, label='総会話数')

        ax.set_xlabel('日付')
        ax.set_ylabel('会話数')
        ax.set_title('日別会話数推移')
        ax.legend(loc='upper left')

        # X軸ラベルを間引いて表示
        step = max(1, len(dates) // 10)
        ax.set_xticks(x[::step])
        ax.set_xticklabels([d[5:] for d in dates[::step]], rotation=45, ha='right')  # MM-DD形式

        plt.tight_layout()
        path = self._get_chart_path("daily")
        plt.savefig(path, bbox_inches='tight', facecolor='white')
        plt.close()
        return path

    def generate_comparison_chart(self, data: dict) -> str:
        """前月比較グラフ"""
        current = data['current']
        previous = data['previous']

        categories = ['総会話数', '回答できた', '回答できなかった', 'いいね', 'よくない']
        current_values = [
            current['total_conversations'],
            current['answered_count'],
            current['unanswered_count'],
            current['likes_count'],
            current['dislikes_count'],
        ]
        previous_values = [
            previous['total_conversations'],
            previous['answered_count'],
            previous['unanswered_count'],
            previous['likes_count'],
            previous['dislikes_count'],
        ]

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

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

        ax.bar(x - width/2, previous_values, width, label='前月', color='#9E9E9E', alpha=0.7)
        ax.bar(x + width/2, current_values, width, label='当月', color='#2196F3', alpha=0.8)

        ax.set_ylabel('件数')
        ax.set_title('前月比較')
        ax.set_xticks(x)
        ax.set_xticklabels(categories)
        ax.legend()

        # 値をバーの上に表示
        for i, (c, p) in enumerate(zip(current_values, previous_values)):
            ax.annotate(str(c), xy=(i + width/2, c), ha='center', va='bottom', fontsize=8)
            ax.annotate(str(p), xy=(i - width/2, p), ha='center', va='bottom', fontsize=8)

        plt.tight_layout()
        path = self._get_chart_path("comparison")
        plt.savefig(path, bbox_inches='tight', facecolor='white')
        plt.close()
        return path

    def generate_hourly_chart(self, data: list) -> str:
        """時間帯別分布"""
        if not data:
            return self._generate_empty_chart("時間帯別分布", "データがありません")

        # 0-23時のデータを準備
        hourly = {h: {'total': 0, 'unanswered': 0} for h in range(24)}
        for d in data:
            h = int(d['hour'])
            hourly[h]['total'] = d['total_conversations']
            hourly[h]['unanswered'] = d['unanswered_count']

        hours = list(range(24))
        totals = [hourly[h]['total'] for h in hours]
        unanswered = [hourly[h]['unanswered'] for h in hours]

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

        ax.bar(hours, totals, color='#2196F3', alpha=0.7, label='総会話数')
        ax.bar(hours, unanswered, color='#F44336', alpha=0.8, label='未解決')

        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', fontsize=8)
        ax.legend()

        plt.tight_layout()
        path = self._get_chart_path("hourly")
        plt.savefig(path, bbox_inches='tight', facecolor='white')
        plt.close()
        return path

    def generate_day_of_week_chart(self, data: list) -> str:
        """曜日別傾向"""
        if not data:
            return self._generate_empty_chart("曜日別傾向", "データがありません")

        dow_names = ['月', '火', '水', '木', '金', '土', '日']

        # データを整形
        dow_data = {i: {'total': 0, 'unanswered': 0} for i in range(7)}
        for d in data:
            dow = int(d['day_of_week'])
            dow_data[dow]['total'] = d['total_conversations']
            dow_data[dow]['unanswered'] = d['unanswered_count']

        totals = [dow_data[i]['total'] for i in range(7)]
        unanswered = [dow_data[i]['unanswered'] for i in range(7)]

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

        x = np.arange(7)
        width = 0.6

        answered = [t - u for t, u in zip(totals, unanswered)]
        ax.bar(x, answered, width, label='回答できた', color='#4CAF50', alpha=0.8)
        ax.bar(x, unanswered, width, bottom=answered, label='回答できなかった', color='#F44336', alpha=0.8)

        ax.set_xlabel('曜日')
        ax.set_ylabel('会話数')
        ax.set_title('曜日別会話数')
        ax.set_xticks(x)
        ax.set_xticklabels(dow_names)
        ax.legend()

        plt.tight_layout()
        path = self._get_chart_path("day_of_week")
        plt.savefig(path, bbox_inches='tight', facecolor='white')
        plt.close()
        return path

    def generate_heatmap(self, data: list) -> str:
        """曜日×時間帯ヒートマップ"""
        import seaborn as sns

        # 7(曜日) x 24(時間) のマトリックスを作成
        matrix = np.zeros((7, 24))
        for d in data:
            dow = int(d['day_of_week'])
            hour = int(d['hour'])
            matrix[dow][hour] = d['count']

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

        dow_names = ['月', '火', '水', '木', '金', '土', '日']

        sns.heatmap(
            matrix,
            ax=ax,
            cmap='YlOrRd',
            xticklabels=[f'{h}時' for h in range(24)],
            yticklabels=dow_names,
            cbar_kws={'label': '会話数'},
            annot=False,
        )

        ax.set_xlabel('時間帯')
        ax.set_ylabel('曜日')
        ax.set_title('曜日×時間帯 会話数分布')

        plt.tight_layout()
        path = self._get_chart_path("heatmap")
        plt.savefig(path, bbox_inches='tight', facecolor='white')
        plt.close()
        return path

    def generate_keywords_chart(self, data: list) -> str:
        """頻出キーワード横棒グラフ"""
        if not data:
            return self._generate_empty_chart("頻出キーワード", "データがありません")

        # 上位を表示（逆順で下から上へ）
        keywords = [d[0] for d in data[:15]][::-1]
        counts = [d[1] for d in data[:15]][::-1]

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

        y = np.arange(len(keywords))
        ax.barh(y, counts, color='#2196F3', alpha=0.8)

        ax.set_yticks(y)
        ax.set_yticklabels(keywords)
        ax.set_xlabel('出現回数')
        ax.set_title('頻出キーワード TOP15')

        # 値をバーの右に表示
        for i, v in enumerate(counts):
            ax.text(v + 0.5, i, str(v), va='center', fontsize=8)

        plt.tight_layout()
        path = self._get_chart_path("keywords")
        plt.savefig(path, bbox_inches='tight', facecolor='white')
        plt.close()
        return path

    def generate_unresolved_keywords_chart(self, data: list) -> str:
        """未解決キーワード横棒グラフ"""
        if not data:
            return self._generate_empty_chart("未解決キーワード", "データがありません")

        keywords = [d[0] for d in data[:15]][::-1]
        counts = [d[1] for d in data[:15]][::-1]

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

        y = np.arange(len(keywords))
        ax.barh(y, counts, color='#F44336', alpha=0.8)

        ax.set_yticks(y)
        ax.set_yticklabels(keywords)
        ax.set_xlabel('出現回数')
        ax.set_title('未解決に多いキーワード')

        for i, v in enumerate(counts):
            ax.text(v + 0.5, i, str(v), va='center', fontsize=8)

        plt.tight_layout()
        path = self._get_chart_path("unresolved_keywords")
        plt.savefig(path, bbox_inches='tight', facecolor='white')
        plt.close()
        return path

    def generate_feedback_chart(self, data: list) -> str:
        """フィードバック日別推移"""
        if not data:
            return self._generate_empty_chart("フィードバック推移", "データがありません")

        dates = [d['date'] for d in data]
        likes = [d['likes'] for d in data]
        dislikes = [d['dislikes'] for d in data]

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

        x = np.arange(len(dates))

        ax.plot(x, likes, 'o-', color='#4CAF50', linewidth=2, markersize=4, label='いいね')
        ax.plot(x, dislikes, 'o-', color='#F44336', linewidth=2, markersize=4, label='よくない')

        ax.set_xlabel('日付')
        ax.set_ylabel('件数')
        ax.set_title('フィードバック推移')
        ax.legend()

        step = max(1, len(dates) // 10)
        ax.set_xticks(x[::step])
        ax.set_xticklabels([d[5:] for d in dates[::step]], rotation=45, ha='right')

        plt.tight_layout()
        path = self._get_chart_path("feedback")
        plt.savefig(path, bbox_inches='tight', facecolor='white')
        plt.close()
        return path

    def generate_satisfaction_pie(self, likes: int, dislikes: int) -> str:
        """満足度円グラフ"""
        total = likes + dislikes
        if total == 0:
            return self._generate_empty_chart("満足度", "フィードバックがありません")

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

        sizes = [likes, dislikes]
        labels = [f'いいね\n{likes}件', f'よくない\n{dislikes}件']
        colors = ['#4CAF50', '#F44336']
        explode = (0.05, 0)

        ax.pie(
            sizes,
            labels=labels,
            colors=colors,
            explode=explode,
            autopct='%1.1f%%',
            startangle=90,
            textprops={'fontsize': 10}
        )
        ax.set_title(f'フィードバック内訳（計{total}件）')

        plt.tight_layout()
        path = self._get_chart_path("satisfaction_pie")
        plt.savefig(path, bbox_inches='tight', facecolor='white')
        plt.close()
        return path

    def generate_resolution_pie(self, answered: int, unanswered: int) -> str:
        """回答可否円グラフ"""
        total = answered + unanswered
        if total == 0:
            return self._generate_empty_chart("回答可否", "データがありません")

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

        sizes = [answered, unanswered]
        labels = [f'回答できた\n{answered}件', f'回答できなかった\n{unanswered}件']
        colors = ['#4CAF50', '#F44336']
        explode = (0.05, 0)

        ax.pie(
            sizes,
            labels=labels,
            colors=colors,
            explode=explode,
            autopct='%1.1f%%',
            startangle=90,
            textprops={'fontsize': 10}
        )
        ax.set_title(f'回答可否の内訳（計{total}件）')

        plt.tight_layout()
        path = self._get_chart_path("resolution_pie")
        plt.savefig(path, bbox_inches='tight', facecolor='white')
        plt.close()
        return path

    def _generate_empty_chart(self, title: str, message: str) -> str:
        """空のチャート（データなし時）"""
        fig, ax = plt.subplots(figsize=(8, 4))
        ax.text(0.5, 0.5, message, ha='center', va='center', fontsize=14, color='gray')
        ax.set_title(title)
        ax.set_xlim(0, 1)
        ax.set_ylim(0, 1)
        ax.axis('off')

        plt.tight_layout()
        path = self._get_chart_path("empty")
        plt.savefig(path, bbox_inches='tight', facecolor='white')
        plt.close()
        return path

    def cleanup(self):
        """一時ファイル削除"""
        import shutil
        if os.path.exists(self.output_dir):
            try:
                shutil.rmtree(self.output_dir)
            except Exception:
                pass
