import os
import json
import sqlite3
import datetime
from typing import Dict, List, Any, Optional
import logging
from pathlib import Path

from .config import Config

# 创建Config实例
config = Config()

class DataManager:
    def __init__(self):
        # 确保目录存在
        os.makedirs(os.path.dirname(config.DB_FILE), exist_ok=True)
        
        # 初始化数据库
        self._init_db()
        
        # 加载式神数据
        self.shikigami_data = self._load_shikigami_data()
    
    def _init_db(self):
        """初始化数据库"""
        with sqlite3.connect(config.DB_FILE) as conn:
            cursor = conn.cursor()
            
            # 创建式神表
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS shikigami (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    name TEXT NOT NULL,
                    rarity TEXT NOT NULL,
                    image_path TEXT NOT NULL
                )
            """)
            
            # 创建每日抽卡记录表
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS daily_draws (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    date TEXT NOT NULL,
                    user_id TEXT NOT NULL,
                    rarity TEXT NOT NULL,
                    shikigami_id INTEGER NOT NULL,
                    timestamp TEXT NOT NULL,
                    FOREIGN KEY (shikigami_id) REFERENCES shikigami(id)
                )
            """)
            
            # 创建用户统计表
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS user_stats (
                    user_id TEXT PRIMARY KEY,
                    total_draws INTEGER DEFAULT 0,
                    R_count INTEGER DEFAULT 0,
                    SR_count INTEGER DEFAULT 0,
                    SSR_count INTEGER DEFAULT 0,
                    SP_count INTEGER DEFAULT 0
                )
            """)
            
            # 创建抽卡历史表
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS draw_history (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    user_id TEXT NOT NULL,
                    date TEXT NOT NULL,
                    rarity TEXT NOT NULL,
                    shikigami_id INTEGER NOT NULL,
                    FOREIGN KEY (user_id) REFERENCES user_stats(user_id),
                    FOREIGN KEY (shikigami_id) REFERENCES shikigami(id)
                )
            """)
            
            # 创建成就表
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS achievements (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    user_id TEXT NOT NULL,
                    achievement_id TEXT NOT NULL,
                    unlocked_date TEXT NOT NULL,
                    reward_claimed INTEGER DEFAULT 0,
                    UNIQUE(user_id, achievement_id)
                )
            """)
            
            # 创建用户成就进度表
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS user_achievement_progress (
                    user_id TEXT PRIMARY KEY,
                    consecutive_days INTEGER DEFAULT 0,
                    last_draw_date TEXT DEFAULT '',
                    no_ssr_streak INTEGER DEFAULT 0,
                    total_consecutive_days INTEGER DEFAULT 0
                )
            """)

            self._init_sign_in_table(cursor)
            
            conn.commit()

    def _init_sign_in_table(self, cursor: sqlite3.Cursor) -> None:
        """创建每日签到表"""
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS daily_sign_in (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_id TEXT NOT NULL,
                sign_date TEXT NOT NULL,
                points_awarded INTEGER NOT NULL,
                created_at TEXT NOT NULL,
                UNIQUE(user_id, sign_date)
            )
        """)
    
    def update_achievement_progress(self, user_id: str, rarity: str) -> List[str]:
        """更新用户成就进度，返回新解锁的成就列表"""
        today = self.get_today_date()
        unlocked_achievements = []
        
        with sqlite3.connect(config.DB_FILE) as conn:
            cursor = conn.cursor()
            
            # 获取或创建用户成就进度
            cursor.execute(
                "SELECT * FROM user_achievement_progress WHERE user_id = ?",
                (user_id,)
            )
            progress = cursor.fetchone()
            
            if not progress:
                cursor.execute(
                    "INSERT INTO user_achievement_progress (user_id, last_draw_date) VALUES (?, ?)",
                    (user_id, today)
                )
                consecutive_days = 1
                no_ssr_streak = 1 if rarity not in ["SSR", "SP"] else 0
                total_consecutive_days = 1
            else:
                last_draw_date = progress[2]
                consecutive_days = progress[1]
                no_ssr_streak = progress[3]
                total_consecutive_days = progress[4]
                
                # 更新连续抽卡天数
                if last_draw_date != today:
                    # 检查是否是连续的一天
                    last_date = datetime.datetime.strptime(last_draw_date, "%Y-%m-%d")
                    current_date = datetime.datetime.strptime(today, "%Y-%m-%d")
                    days_diff = (current_date - last_date).days
                    
                    if days_diff == 1:
                        consecutive_days += 1
                        total_consecutive_days += 1
                    elif days_diff > 1:
                        consecutive_days = 1
                        total_consecutive_days += 1
                    # days_diff == 0 表示今天已经抽过卡了，不更新连续天数
                
                # 更新无SSR连击数
                if rarity in ["SSR", "SP"]:
                    no_ssr_streak = 0
                else:
                    no_ssr_streak += 1
            
            # 更新进度
            cursor.execute("""
                INSERT OR REPLACE INTO user_achievement_progress 
                (user_id, consecutive_days, last_draw_date, no_ssr_streak, total_consecutive_days)
                VALUES (?, ?, ?, ?, ?)
            """, (user_id, consecutive_days, today, no_ssr_streak, total_consecutive_days))
            
            # 检查是否解锁新成就
            for achievement_id, achievement_config in config.ACHIEVEMENTS.items():
                # 对于可重复获得的成就（勤勤恳恳系列），需要特殊处理
                if achievement_config.get("repeatable", False) and achievement_config["type"] == "consecutive_days":
                    # 检查连续抽卡成就的升级逻辑
                    if consecutive_days >= achievement_config["threshold"]:
                        # 检查是否已经解锁过这个等级
                        cursor.execute(
                            "SELECT id FROM achievements WHERE user_id = ? AND achievement_id = ?",
                            (user_id, achievement_id)
                        )
                        if not cursor.fetchone():
                            # 解锁新等级的成就
                            cursor.execute("""
                                INSERT INTO achievements (user_id, achievement_id, unlocked_date)
                                VALUES (?, ?, ?)
                            """, (user_id, achievement_id, today))
                            unlocked_achievements.append(achievement_id)
                        
                        # 如果是最高等级（Ⅴ），检查是否需要给重复奖励
                        elif achievement_config["level"] == 5 and consecutive_days >= 150:
                            # 每30天给一次重复奖励
                            days_over_150 = consecutive_days - 150
                            if days_over_150 > 0 and days_over_150 % 30 == 0:
                                # 检查这个重复奖励是否已经给过
                                repeat_id = f"{achievement_id}_repeat_{days_over_150//30}"
                                cursor.execute(
                                    "SELECT id FROM achievements WHERE user_id = ? AND achievement_id = ?",
                                    (user_id, repeat_id)
                                )
                                if not cursor.fetchone():
                                    cursor.execute("""
                                        INSERT INTO achievements (user_id, achievement_id, unlocked_date)
                                        VALUES (?, ?, ?)
                                    """, (user_id, repeat_id, today))
                                    unlocked_achievements.append(achievement_id)
                else:
                    # 非重复成就的原有逻辑
                    # 检查是否已经解锁
                    cursor.execute(
                        "SELECT id FROM achievements WHERE user_id = ? AND achievement_id = ?",
                        (user_id, achievement_id)
                    )
                    if cursor.fetchone():
                        continue
                    
                    # 检查成就条件
                    unlocked = False
                    if achievement_config["type"] == "consecutive_days":
                        if consecutive_days >= achievement_config["threshold"]:
                            unlocked = True
                    elif achievement_config["type"] == "no_ssr_streak":
                        if no_ssr_streak >= achievement_config["threshold"]:
                            unlocked = True
                    
                    if unlocked:
                        cursor.execute("""
                            INSERT INTO achievements (user_id, achievement_id, unlocked_date)
                            VALUES (?, ?, ?)
                        """, (user_id, achievement_id, today))
                        unlocked_achievements.append(achievement_id)
            
            conn.commit()
        
        return unlocked_achievements
    
    def get_user_achievements(self, user_id: str) -> Dict[str, Any]:
        """获取用户成就信息"""
        with sqlite3.connect(config.DB_FILE) as conn:
            conn.row_factory = sqlite3.Row
            cursor = conn.cursor()
            
            # 获取已解锁的成就
            cursor.execute(
                "SELECT achievement_id, unlocked_date, reward_claimed FROM achievements WHERE user_id = ?",
                (user_id,)
            )
            unlocked = {row["achievement_id"]: {
                "unlocked_date": row["unlocked_date"],
                "reward_claimed": bool(row["reward_claimed"])
            } for row in cursor.fetchall()}
            
            # 获取进度
            cursor.execute(
                "SELECT * FROM user_achievement_progress WHERE user_id = ?",
                (user_id,)
            )
            progress_row = cursor.fetchone()
            
            if not progress_row:
                progress = {
                    "consecutive_days": 0,
                    "no_ssr_streak": 0,
                    "total_consecutive_days": 0
                }
            else:
                progress = {
                    "consecutive_days": progress_row["consecutive_days"],
                    "no_ssr_streak": progress_row["no_ssr_streak"],
                    "total_consecutive_days": progress_row["total_consecutive_days"]
                }
            
            return {
                "unlocked": unlocked,
                "progress": progress
            }
    
    def claim_achievement_reward(self, user_id: str, achievement_id: str) -> bool:
        """领取成就奖励"""
        with sqlite3.connect(config.DB_FILE) as conn:
            cursor = conn.cursor()
            
            cursor.execute("""
                UPDATE achievements 
                SET reward_claimed = 1 
                WHERE user_id = ? AND achievement_id = ? AND reward_claimed = 0
            """, (user_id, achievement_id))
            
            conn.commit()
            return cursor.rowcount > 0


    def _load_shikigami_data(self) -> Dict[str, List[Dict[str, str]]]:
        """加载式神数据到数据库"""
        result = {"R": [], "SR": [], "SSR": [], "SP": []}
        rarity_dirs = {
            "R": "r", 
            "SR": "sr", 
            "SSR": "ssr", 
            "SP": "sp"
        }
        
        with sqlite3.connect(config.DB_FILE) as conn:
            cursor = conn.cursor()
            
            # 清空现有式神数据
            cursor.execute("DELETE FROM shikigami")
            
            for rarity, dir_name in rarity_dirs.items():
                dir_path = os.path.join(config.SHIKIGAMI_IMG_DIR, dir_name)
                if os.path.exists(dir_path):
                    for file_name in os.listdir(dir_path):
                        if file_name.endswith(('.png', '.jpg', '.jpeg')):
                            name = os.path.splitext(file_name)[0]
                            image_path = os.path.join(dir_path, file_name)
                            
                            # 插入式神数据
                            cursor.execute(
                                "INSERT INTO shikigami (name, rarity, image_path) VALUES (?, ?, ?)",
                                (name, rarity, image_path)
                            )
                            
                            result[rarity].append({
                                "name": name,
                                "image_url": image_path
                            })
            
            conn.commit()
        
        return result
    
    def get_today_date(self) -> str:
        """获取当前日期字符串"""
        return datetime.datetime.now().strftime("%Y-%m-%d")

    def has_signed_in_today(self, user_id: str) -> bool:
        """检查用户今天是否已签到"""
        today = self.get_today_date()
        with sqlite3.connect(config.DB_FILE) as conn:
            cursor = conn.cursor()
            cursor.execute(
                "SELECT 1 FROM daily_sign_in WHERE user_id = ? AND sign_date = ? LIMIT 1",
                (user_id, today),
            )
            return cursor.fetchone() is not None

    def record_sign_in(self, user_id: str, points_awarded: int) -> bool:
        """记录每日签到，重复签到返回False"""
        today = self.get_today_date()
        created_at = datetime.datetime.now().isoformat()
        try:
            with sqlite3.connect(config.DB_FILE) as conn:
                cursor = conn.cursor()
                cursor.execute("""
                    INSERT INTO daily_sign_in (user_id, sign_date, points_awarded, created_at)
                    VALUES (?, ?, ?, ?)
                """, (user_id, today, points_awarded, created_at))
                conn.commit()
                return True
        except sqlite3.IntegrityError:
            return False
    
    def get_current_time(self) -> str:
        """获取当前时间字符串"""
        return datetime.datetime.now().strftime("%H:%M:%S")
    
    def get_daily_draws(self) -> Dict[str, Dict[str, List[Dict[str, str]]]]:
        """获取每日抽卡记录"""
        result = {}
        today = self.get_today_date()
        
        with sqlite3.connect(config.DB_FILE) as conn:
            conn.row_factory = sqlite3.Row
            cursor = conn.cursor()
            
            # 先查询今日的抽卡记录
            cursor.execute("""
                SELECT date, user_id, rarity, shikigami_id, timestamp 
                FROM daily_draws
                WHERE date = ?
                ORDER BY timestamp
            """, (today,))
            
            rows = cursor.fetchall()
            
            # 获取所有涉及的式神ID
            shikigami_ids = list(set(row["shikigami_id"] for row in rows))
            
            # 查询式神信息
            shikigami_info = {}
            if shikigami_ids:
                placeholders = ','.join('?' * len(shikigami_ids))
                cursor.execute(f"""
                    SELECT id, name, rarity 
                    FROM shikigami 
                    WHERE id IN ({placeholders})
                """, shikigami_ids)
                
                for shikigami_row in cursor.fetchall():
                    shikigami_info[shikigami_row["id"]] = {
                        "name": shikigami_row["name"],
                        "rarity": shikigami_row["rarity"]
                    }
            
            # 构建结果
            for row in rows:
                date = row["date"]
                user_id = row["user_id"]
                shikigami_id = row["shikigami_id"]
                
                if date not in result:
                    result[date] = {}
                
                if user_id not in result[date]:
                    result[date][user_id] = []
                
                # 如果找不到式神信息，使用daily_draws表中的稀有度和默认名称
                if shikigami_id in shikigami_info:
                    name = shikigami_info[shikigami_id]["name"]
                    rarity = shikigami_info[shikigami_id]["rarity"]
                else:
                    name = f"式神{shikigami_id}"
                    rarity = row["rarity"]
                
                result[date][user_id].append({
                    "rarity": rarity,
                    "name": name,
                    "timestamp": row["timestamp"]
                })
        
        return result
    
    def save_daily_draws(self, data: Dict[str, Dict[str, List[Dict[str, str]]]]):
        """保存每日抽卡记录"""
        # SQLite实现中此方法为空，因为记录时直接插入数据库
        pass
    
    def get_user_stats(self) -> Dict[str, Dict[str, Any]]:
        """获取用户统计数据"""
        result = {}
        
        with sqlite3.connect(config.DB_FILE) as conn:
            conn.row_factory = sqlite3.Row
            cursor = conn.cursor()
            
            # 获取基础统计
            cursor.execute("SELECT * FROM user_stats")
            user_stats = cursor.fetchall()
            
            for stat in user_stats:
                user_id = stat["user_id"]
                result[user_id] = {
                    "total_draws": stat["total_draws"],
                    "R_count": stat["R_count"],
                    "SR_count": stat["SR_count"],
                    "SSR_count": stat["SSR_count"],
                    "SP_count": stat["SP_count"],
                    "draw_history": []
                }
                
                # 获取抽卡历史
                cursor.execute("""
                    SELECT draw_history.date, draw_history.rarity, shikigami.name
                    FROM draw_history
                    JOIN shikigami ON draw_history.shikigami_id = shikigami.id
                    WHERE draw_history.user_id = ?
                    ORDER BY draw_history.date DESC
                    LIMIT 100
                """, (user_id,))
                
                history = cursor.fetchall()
                result[user_id]["draw_history"] = [
                    {
                        "date": row["date"],
                        "rarity": row["rarity"],
                        "name": row["name"]
                    } for row in history
                ]
        
        return result
    
    def save_user_stats(self, data: Dict[str, Dict[str, Any]]):
        """保存用户统计数据"""
        # SQLite实现中此方法为空，因为统计时直接更新数据库
        pass
    
    def check_daily_limit(self, user_id: str) -> bool:
        """检查用户是否达到每日抽卡限制"""
        today = self.get_today_date()
        
        with sqlite3.connect(config.DB_FILE) as conn:
            cursor = conn.cursor()
            
            cursor.execute("""
                SELECT COUNT(*) 
                FROM daily_draws 
                WHERE date = ? AND user_id = ?
            """, (today, user_id))
            
            count = cursor.fetchone()[0]
            
        return count < config.DAILY_LIMIT
    
    def get_draws_left(self, user_id: str) -> int:
        """获取用户今日剩余抽卡次数"""
        today = self.get_today_date()
        
        with sqlite3.connect(config.DB_FILE) as conn:
            cursor = conn.cursor()
            
            cursor.execute("""
                SELECT COUNT(*) 
                FROM daily_draws 
                WHERE date = ? AND user_id = ?
            """, (today, user_id))
            
            count = cursor.fetchone()[0]
            
        return max(0, config.DAILY_LIMIT - count)
    
    def record_draw(self, user_id: str, rarity: str, shikigami_name: str) -> List[str]:
        """记录一次抽卡，返回新解锁的成就列表"""
        today = self.get_today_date()
        current_time = self.get_current_time()
        
        with sqlite3.connect(config.DB_FILE) as conn:
            cursor = conn.cursor()
            
            # 获取式神ID
            cursor.execute(
                "SELECT id FROM shikigami WHERE name = ? AND rarity = ?",
                (shikigami_name, rarity)
            )
            shikigami_id = cursor.fetchone()
            
            if not shikigami_id:
                logging.error(f"找不到式神: {shikigami_name} ({rarity})")
                return []
            
            shikigami_id = shikigami_id[0]
            
            # 记录每日抽卡
            cursor.execute("""
                INSERT INTO daily_draws (date, user_id, rarity, shikigami_id, timestamp)
                VALUES (?, ?, ?, ?, ?)
            """, (today, user_id, rarity, shikigami_id, current_time))
            
            # 更新用户统计
            cursor.execute("""
                INSERT OR IGNORE INTO user_stats (user_id) VALUES (?)
            """, (user_id,))
            
            cursor.execute("""
                UPDATE user_stats 
                SET total_draws = total_draws + 1,
                    R_count = R_count + ?,
                    SR_count = SR_count + ?,
                    SSR_count = SSR_count + ?,
                    SP_count = SP_count + ?
                WHERE user_id = ?
            """, (
                1 if rarity == "R" else 0,
                1 if rarity == "SR" else 0,
                1 if rarity == "SSR" else 0,
                1 if rarity == "SP" else 0,
                user_id
            ))
            
            # 添加抽卡历史
            cursor.execute("""
                INSERT INTO draw_history (user_id, date, rarity, shikigami_id)
                VALUES (?, ?, ?, ?)
            """, (user_id, today, rarity, shikigami_id))
            
            # 保持历史记录不超过100条
            cursor.execute("""
                DELETE FROM draw_history
                WHERE user_id = ? AND id NOT IN (
                    SELECT id FROM draw_history
                    WHERE user_id = ?
                    ORDER BY date DESC
                    LIMIT 100
                )
            """, (user_id, user_id))
            
            conn.commit()
        
        # 更新成就进度
        unlocked_achievements = self.update_achievement_progress(user_id, rarity)
        return unlocked_achievements
