#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
AI 生成歷史記錄服務
提供 AI 生成結果的 CRUD 操作
"""

import json
import logging
from typing import List, Dict, Any, Optional
from datetime import datetime, timedelta
from sqlalchemy import desc, func, or_
from database.manager import get_session
from database.ai_models import AIGenerationHistory, AIPromptTemplate

logger = logging.getLogger(__name__)


class AIHistoryService:
    """AI 生成歷史記錄服務"""

    @staticmethod
    def save_generation(
        generation_type: str,
        output_content: str,
        product_name: str = None,
        input_keywords: List[str] = None,
        input_style: str = None,
        input_trend_topic: str = None,
        model_name: str = None,
        generation_duration: float = None,
        created_by: int = None,
        ai_provider: str = 'ollama',
        input_tokens: int = 0,
        output_tokens: int = 0
    ) -> Optional[int]:
        """
        儲存 AI 生成結果

        Args:
            generation_type: 生成類型 (copy/recommend/weather_analysis)
            output_content: 生成的內容
            product_name: 商品名稱
            input_keywords: 輸入的關鍵字列表
            input_style: 文案風格
            input_trend_topic: 趨勢話題
            model_name: 使用的模型名稱
            generation_duration: 生成耗時（秒）
            created_by: 創建者用戶 ID
            ai_provider: AI 提供者 ('ollama' 或 'gemini')
            input_tokens: 輸入 token 數量
            output_tokens: 輸出 token 數量

        Returns:
            新建記錄的 ID，失敗則返回 None
        """
        session = get_session()
        try:
            history = AIGenerationHistory(
                generation_type=generation_type,
                product_name=product_name,
                input_keywords=AIHistoryService._safe_json_dumps(input_keywords),
                input_style=input_style,
                input_trend_topic=input_trend_topic,
                output_content=output_content,
                model_name=model_name,
                generation_duration=generation_duration,
                created_by=created_by,
                ai_provider=ai_provider,
                input_tokens=input_tokens,
                output_tokens=output_tokens
            )
            session.add(history)
            session.commit()
            logger.info(f"AI 生成記錄已儲存 | ID: {history.id} | Type: {generation_type} | Provider: {ai_provider}")
            return history.id
        except Exception as e:
            session.rollback()
            logger.error(f"儲存 AI 生成記錄失敗: {e}")
            return None
        finally:
            session.close()

    @staticmethod
    def _safe_json_dumps(data) -> Optional[str]:
        """安全的 JSON 序列化"""
        if data is None:
            return None
        try:
            return json.dumps(data, ensure_ascii=False)
        except (TypeError, ValueError) as e:
            logger.warning(f"JSON 序列化失敗，使用字串轉換: {e}")
            return json.dumps(str(data), ensure_ascii=False)

    @staticmethod
    def get_history_list(
        page: int = 1,
        per_page: int = 20,
        generation_type: str = None,
        search: str = None,
        is_favorite: bool = None,
        start_date: datetime = None,
        end_date: datetime = None,
        created_by: int = None
    ) -> Dict[str, Any]:
        """
        獲取生成歷史列表（分頁）

        Args:
            page: 頁碼（從 1 開始）
            per_page: 每頁數量
            generation_type: 篩選生成類型
            search: 搜尋關鍵字（商品名稱或內容）
            is_favorite: 篩選收藏
            start_date: 開始日期
            end_date: 結束日期
            created_by: 創建者用戶 ID

        Returns:
            包含 items, total, page, per_page, total_pages 的字典
        """
        # 輸入驗證
        page = max(1, page)
        per_page = max(1, min(100, per_page))  # 限制每頁最多 100 筆

        session = get_session()
        try:
            query = session.query(AIGenerationHistory)

            # 應用篩選條件
            if generation_type:
                query = query.filter(AIGenerationHistory.generation_type == generation_type)

            if search:
                search_pattern = f"%{search}%"
                query = query.filter(
                    or_(
                        AIGenerationHistory.product_name.like(search_pattern),
                        AIGenerationHistory.output_content.like(search_pattern),
                        AIGenerationHistory.input_trend_topic.like(search_pattern)
                    )
                )

            if is_favorite is not None:
                query = query.filter(AIGenerationHistory.is_favorite.is_(is_favorite))

            if start_date:
                query = query.filter(AIGenerationHistory.created_at >= start_date)

            if end_date:
                query = query.filter(AIGenerationHistory.created_at <= end_date)

            if created_by:
                query = query.filter(AIGenerationHistory.created_by == created_by)

            # 計算總數
            total = query.count()

            # 排序和分頁
            query = query.order_by(desc(AIGenerationHistory.created_at))
            offset = (page - 1) * per_page
            items = query.offset(offset).limit(per_page).all()

            return {
                'items': [item.to_dict() for item in items],
                'total': total,
                'page': page,
                'per_page': per_page,
                'total_pages': (total + per_page - 1) // per_page
            }

        except Exception as e:
            logger.error(f"獲取 AI 生成歷史列表失敗: {e}")
            return {
                'items': [],
                'total': 0,
                'page': page,
                'per_page': per_page,
                'total_pages': 0
            }
        finally:
            session.close()

    @staticmethod
    def get_by_id(history_id: int) -> Optional[Dict[str, Any]]:
        """
        根據 ID 獲取單筆記錄

        Args:
            history_id: 記錄 ID

        Returns:
            記錄字典，不存在則返回 None
        """
        session = get_session()
        try:
            history = session.query(AIGenerationHistory).filter_by(id=history_id).first()
            return history.to_dict() if history else None
        except Exception as e:
            logger.error(f"獲取 AI 生成記錄失敗: {e}")
            return None
        finally:
            session.close()

    @staticmethod
    def update(
        history_id: int,
        output_content: str = None,
        rating: int = None,
        is_favorite: bool = None,
        is_used: bool = None,
        notes: str = None
    ) -> bool:
        """
        更新生成記錄

        Args:
            history_id: 記錄 ID
            output_content: 更新後的內容
            rating: 評分 (1-5)
            is_favorite: 是否收藏
            is_used: 是否已使用
            notes: 備註

        Returns:
            是否更新成功
        """
        session = get_session()
        try:
            history = session.query(AIGenerationHistory).filter_by(id=history_id).first()
            if not history:
                return False

            if output_content is not None:
                history.output_content = output_content
            if rating is not None:
                history.rating = max(1, min(5, rating))  # 限制 1-5
            if is_favorite is not None:
                history.is_favorite = is_favorite
            if is_used is not None:
                history.is_used = is_used
            if notes is not None:
                history.notes = notes

            history.updated_at = datetime.now()
            session.commit()
            logger.info(f"AI 生成記錄已更新 | ID: {history_id}")
            return True

        except Exception as e:
            session.rollback()
            logger.error(f"更新 AI 生成記錄失敗: {e}")
            return False
        finally:
            session.close()

    @staticmethod
    def delete(history_id: int) -> bool:
        """
        刪除生成記錄

        Args:
            history_id: 記錄 ID

        Returns:
            是否刪除成功
        """
        session = get_session()
        try:
            history = session.query(AIGenerationHistory).filter_by(id=history_id).first()
            if not history:
                return False

            session.delete(history)
            session.commit()
            logger.info(f"AI 生成記錄已刪除 | ID: {history_id}")
            return True

        except Exception as e:
            session.rollback()
            logger.error(f"刪除 AI 生成記錄失敗: {e}")
            return False
        finally:
            session.close()

    @staticmethod
    def batch_delete(history_ids: List[int]) -> Dict[str, Any]:
        """
        批次刪除生成記錄（優化版本：使用批次刪除）

        Args:
            history_ids: 記錄 ID 列表

        Returns:
            包含 success_count 和 failed_ids 的字典
        """
        if not history_ids:
            return {'success_count': 0, 'failed_ids': []}

        session = get_session()
        try:
            # 先查詢存在的 ID
            existing_ids = session.query(AIGenerationHistory.id).filter(
                AIGenerationHistory.id.in_(history_ids)
            ).all()
            existing_id_set = {row[0] for row in existing_ids}

            # 找出不存在的 ID
            failed_ids = [hid for hid in history_ids if hid not in existing_id_set]

            # 批次刪除存在的記錄
            if existing_id_set:
                deleted_count = session.query(AIGenerationHistory).filter(
                    AIGenerationHistory.id.in_(existing_id_set)
                ).delete(synchronize_session=False)
                session.commit()
            else:
                deleted_count = 0

            logger.info(f"批次刪除 AI 生成記錄 | 成功: {deleted_count} | 失敗: {len(failed_ids)}")
            return {
                'success_count': deleted_count,
                'failed_ids': failed_ids
            }

        except Exception as e:
            session.rollback()
            logger.error(f"批次刪除 AI 生成記錄失敗: {e}")
            return {
                'success_count': 0,
                'failed_ids': list(history_ids)
            }
        finally:
            session.close()

    @staticmethod
    def toggle_favorite(history_id: int) -> Optional[bool]:
        """
        切換收藏狀態

        Args:
            history_id: 記錄 ID

        Returns:
            新的收藏狀態，失敗則返回 None
        """
        session = get_session()
        try:
            history = session.query(AIGenerationHistory).filter_by(id=history_id).first()
            if not history:
                return None

            history.is_favorite = not history.is_favorite
            history.updated_at = datetime.now()
            session.commit()
            return history.is_favorite

        except Exception as e:
            session.rollback()
            logger.error(f"切換收藏狀態失敗: {e}")
            return None
        finally:
            session.close()

    @staticmethod
    def get_statistics(days: int = 30, created_by: int = None) -> Dict[str, Any]:
        """
        獲取生成統計資料

        Args:
            days: 統計天數
            created_by: 用戶 ID（可選）

        Returns:
            統計資料字典
        """
        # 輸入驗證
        days = max(1, min(365, days))  # 限制 1-365 天

        session = get_session()
        try:
            start_date = datetime.now() - timedelta(days=days)

            # 建立基礎篩選條件（避免重複使用 query 物件）
            def build_base_filters():
                filters = [AIGenerationHistory.created_at >= start_date]
                if created_by:
                    filters.append(AIGenerationHistory.created_by == created_by)
                return filters

            base_filters = build_base_filters()

            # 總數
            total_count = session.query(AIGenerationHistory).filter(*base_filters).count()

            # 按類型統計
            type_stats = session.query(
                AIGenerationHistory.generation_type,
                func.count(AIGenerationHistory.id)
            ).filter(*base_filters).group_by(AIGenerationHistory.generation_type).all()

            # 收藏數（獨立查詢，避免污染）
            favorite_count = session.query(AIGenerationHistory).filter(
                *base_filters,
                AIGenerationHistory.is_favorite.is_(True)
            ).count()

            # 已使用數（獨立查詢，避免污染）
            used_count = session.query(AIGenerationHistory).filter(
                *base_filters,
                AIGenerationHistory.is_used.is_(True)
            ).count()

            # 平均生成時間
            avg_duration = session.query(
                func.avg(AIGenerationHistory.generation_duration)
            ).filter(
                *base_filters,
                AIGenerationHistory.generation_duration.isnot(None)
            ).scalar() or 0

            # 熱門商品
            popular_products = session.query(
                AIGenerationHistory.product_name,
                func.count(AIGenerationHistory.id).label('count')
            ).filter(
                *base_filters,
                AIGenerationHistory.product_name.isnot(None)
            ).group_by(
                AIGenerationHistory.product_name
            ).order_by(desc('count')).limit(10).all()

            return {
                'total_count': total_count,
                'type_stats': {t: c for t, c in type_stats},
                'favorite_count': favorite_count,
                'used_count': used_count,
                'avg_duration': round(avg_duration, 2),
                'popular_products': [{'name': p, 'count': c} for p, c in popular_products],
                'period_days': days
            }

        except Exception as e:
            logger.error(f"獲取 AI 統計資料失敗: {e}")
            return {
                'total_count': 0,
                'type_stats': {},
                'favorite_count': 0,
                'used_count': 0,
                'avg_duration': 0,
                'popular_products': [],
                'period_days': days
            }
        finally:
            session.close()


class AITemplateService:
    """AI 提示模板服務"""

    @staticmethod
    def get_all_templates(template_type: str = None, active_only: bool = True) -> List[Dict[str, Any]]:
        """
        獲取所有模板

        Args:
            template_type: 篩選類型
            active_only: 是否只返回啟用的模板

        Returns:
            模板列表
        """
        session = get_session()
        try:
            query = session.query(AIPromptTemplate)

            if template_type:
                query = query.filter(AIPromptTemplate.template_type == template_type)

            if active_only:
                query = query.filter(AIPromptTemplate.is_active.is_(True))

            templates = query.order_by(AIPromptTemplate.is_system.desc(), AIPromptTemplate.name).all()
            return [t.to_dict() for t in templates]

        except Exception as e:
            logger.error(f"獲取 AI 模板列表失敗: {e}")
            return []
        finally:
            session.close()

    @staticmethod
    def get_by_id(template_id: int) -> Optional[Dict[str, Any]]:
        """根據 ID 獲取模板"""
        session = get_session()
        try:
            template = session.query(AIPromptTemplate).filter_by(id=template_id).first()
            return template.to_dict() if template else None
        except Exception as e:
            logger.error(f"獲取 AI 模板失敗: {e}")
            return None
        finally:
            session.close()

    @staticmethod
    def create_template(
        name: str,
        template_type: str,
        user_prompt_template: str,
        description: str = None,
        system_prompt: str = None,
        default_temperature: float = 0.7,
        default_style: str = None,
        created_by: int = None
    ) -> Optional[int]:
        """創建新模板"""
        session = get_session()
        try:
            template = AIPromptTemplate(
                name=name,
                description=description,
                template_type=template_type,
                system_prompt=system_prompt,
                user_prompt_template=user_prompt_template,
                default_temperature=default_temperature,
                default_style=default_style,
                is_system=False,
                created_by=created_by
            )
            session.add(template)
            session.commit()
            return template.id
        except Exception as e:
            session.rollback()
            logger.error(f"創建 AI 模板失敗: {e}")
            return None
        finally:
            session.close()

    @staticmethod
    def update_template(template_id: int, **kwargs) -> bool:
        """更新模板"""
        session = get_session()
        try:
            template = session.query(AIPromptTemplate).filter_by(id=template_id).first()
            if not template:
                return False

            # 不允許修改系統模板的核心內容
            if template.is_system:
                allowed_fields = ['is_active']
            else:
                allowed_fields = ['name', 'description', 'system_prompt', 'user_prompt_template',
                                 'default_temperature', 'default_style', 'is_active']

            for field in allowed_fields:
                if field in kwargs and kwargs[field] is not None:
                    setattr(template, field, kwargs[field])

            template.updated_at = datetime.now()
            session.commit()
            return True

        except Exception as e:
            session.rollback()
            logger.error(f"更新 AI 模板失敗: {e}")
            return False
        finally:
            session.close()

    @staticmethod
    def delete_template(template_id: int) -> bool:
        """刪除模板（不能刪除系統模板）"""
        session = get_session()
        try:
            template = session.query(AIPromptTemplate).filter_by(id=template_id).first()
            if not template or template.is_system:
                return False

            session.delete(template)
            session.commit()
            return True

        except Exception as e:
            session.rollback()
            logger.error(f"刪除 AI 模板失敗: {e}")
            return False
        finally:
            session.close()


# 建立全域服務實例
ai_history_service = AIHistoryService()
ai_template_service = AITemplateService()
