"""لایه دیتابیس (SQLite) - سکه‌ها، اخطارها، تاریخچه بازی‌ها، تنظیمات گروه."""
import sqlite3
import threading
import time

import config


class DB:
    def __init__(self, path: str = config.DB_PATH):
        self.conn = sqlite3.connect(path, check_same_thread=False)
        self.conn.row_factory = sqlite3.Row
        self.lock = threading.RLock()
        self._init()

    def _init(self):
        with self.lock:
            self.conn.executescript(
                """
                PRAGMA journal_mode=WAL;
                CREATE TABLE IF NOT EXISTS users(
                    uid TEXT PRIMARY KEY, name TEXT, coins INTEGER NOT NULL,
                    last_daily REAL DEFAULT 0, wins INTEGER DEFAULT 0,
                    losses INTEGER DEFAULT 0);
                CREATE TABLE IF NOT EXISTS members(
                    chat TEXT, uid TEXT, warns INTEGER DEFAULT 0,
                    muted_until REAL DEFAULT 0, banned INTEGER DEFAULT 0,
                    PRIMARY KEY(chat, uid));
                CREATE TABLE IF NOT EXISTS history(
                    id INTEGER PRIMARY KEY AUTOINCREMENT, chat TEXT, game TEXT,
                    players TEXT, bet INTEGER, winner TEXT, prize INTEGER,
                    fee INTEGER, ts REAL);
                CREATE TABLE IF NOT EXISTS settings(
                    chat TEXT, key TEXT, value TEXT, PRIMARY KEY(chat, key));
                CREATE TABLE IF NOT EXISTS badwords(
                    chat TEXT, word TEXT, PRIMARY KEY(chat, word));
                """
            )
            self.conn.commit()

    # ---------- پایه ----------
    def _exec(self, sql, args=()):
        with self.lock:
            cur = self.conn.execute(sql, args)
            self.conn.commit()
            return cur

    def _one(self, sql, args=()):
        with self.lock:
            return self.conn.execute(sql, args).fetchone()

    def _all(self, sql, args=()):
        with self.lock:
            return self.conn.execute(sql, args).fetchall()

    # ---------- کاربر و سکه ----------
    def touch_user(self, uid: str, name: str):
        with self.lock:
            if self._one("SELECT 1 FROM users WHERE uid=?", (uid,)):
                if name:
                    self._exec("UPDATE users SET name=? WHERE uid=?", (name, uid))
            else:
                self._exec("INSERT INTO users(uid,name,coins) VALUES(?,?,?)",
                           (uid, name, config.START_COINS))

    def name(self, uid: str) -> str:
        r = self._one("SELECT name FROM users WHERE uid=?", (uid,))
        return (r["name"] if r and r["name"] else uid[-6:])

    def coins(self, uid: str) -> int:
        r = self._one("SELECT coins FROM users WHERE uid=?", (uid,))
        return r["coins"] if r else 0

    def add_coins(self, uid: str, delta: int) -> bool:
        """اتمی؛ اگر موجودی منفی شود انجام نمی‌شود."""
        with self.lock:
            self.touch_user(uid, "")
            if self.coins(uid) + delta < 0:
                return False
            self._exec("UPDATE users SET coins=coins+? WHERE uid=?", (delta, uid))
            return True

    def transfer(self, a: str, b: str, amount: int) -> bool:
        with self.lock:
            if amount <= 0 or not self.add_coins(a, -amount):
                return False
            self.add_coins(b, amount)
            return True

    def claim_daily(self, uid: str):
        """None اگر هنوز زوده؛ وگرنه True."""
        with self.lock:
            r = self._one("SELECT last_daily FROM users WHERE uid=?", (uid,))
            now = time.time()
            if r and now - r["last_daily"] < 86400:
                return int(86400 - (now - r["last_daily"]))
            self._exec("UPDATE users SET last_daily=?, coins=coins+? WHERE uid=?",
                       (now, config.DAILY_COINS, uid))
            return None

    def top(self, n=10):
        return self._all("SELECT name,coins FROM users ORDER BY coins DESC LIMIT ?", (n,))

    def add_result(self, winner: str, losers: list[str]):
        self._exec("UPDATE users SET wins=wins+1 WHERE uid=?", (winner,))
        for l in losers:
            self._exec("UPDATE users SET losses=losses+1 WHERE uid=?", (l,))

    def stats(self, uid: str):
        return self._one("SELECT wins,losses,coins FROM users WHERE uid=?", (uid,))

    # ---------- تاریخچه ----------
    def add_history(self, chat, game, players, bet, winner, prize, fee):
        self._exec(
            "INSERT INTO history(chat,game,players,bet,winner,prize,fee,ts) VALUES(?,?,?,?,?,?,?,?)",
            (chat, game, ",".join(players), bet, winner, prize, fee, time.time()))

    def history(self, chat, n=8):
        return self._all("SELECT * FROM history WHERE chat=? ORDER BY id DESC LIMIT ?", (chat, n))

    # ---------- اعضا (اخطار / سکوت / بن) ----------
    def _member(self, chat, uid):
        self._exec("INSERT OR IGNORE INTO members(chat,uid) VALUES(?,?)", (chat, uid))
        return self._one("SELECT * FROM members WHERE chat=? AND uid=?", (chat, uid))

    def member(self, chat, uid):
        with self.lock:
            return self._member(chat, uid)

    def add_warn(self, chat, uid) -> int:
        with self.lock:
            self._member(chat, uid)
            self._exec("UPDATE members SET warns=warns+1 WHERE chat=? AND uid=?", (chat, uid))
            return self._one("SELECT warns FROM members WHERE chat=? AND uid=?", (chat, uid))["warns"]

    def remove_warn(self, chat, uid) -> int:
        with self.lock:
            self._member(chat, uid)
            self._exec("UPDATE members SET warns=MAX(warns-1,0) WHERE chat=? AND uid=?", (chat, uid))
            return self._one("SELECT warns FROM members WHERE chat=? AND uid=?", (chat, uid))["warns"]

    def reset_warns(self, chat, uid):
        with self.lock:
            self._member(chat, uid)
            self._exec("UPDATE members SET warns=0 WHERE chat=? AND uid=?", (chat, uid))

    def set_mute(self, chat, uid, until: float):
        with self.lock:
            self._member(chat, uid)
            self._exec("UPDATE members SET muted_until=? WHERE chat=? AND uid=?", (until, chat, uid))

    def set_ban(self, chat, uid, banned: bool):
        with self.lock:
            self._member(chat, uid)
            self._exec("UPDATE members SET banned=? WHERE chat=? AND uid=?", (int(banned), chat, uid))

    # ---------- تنظیمات و کلمات ممنوع ----------
    def get_setting(self, chat, key, default=None):
        r = self._one("SELECT value FROM settings WHERE chat=? AND key=?", (chat, key))
        return r["value"] if r else default

    def set_setting(self, chat, key, value):
        self._exec("INSERT OR REPLACE INTO settings(chat,key,value) VALUES(?,?,?)", (chat, key, str(value)))

    def badwords(self, chat) -> list[str]:
        return [r["word"] for r in self._all("SELECT word FROM badwords WHERE chat=?", (chat,))]

    def add_badword(self, chat, w):
        self._exec("INSERT OR IGNORE INTO badwords(chat,word) VALUES(?,?)", (chat, w))

    def del_badword(self, chat, w):
        self._exec("DELETE FROM badwords WHERE chat=? AND word=?", (chat, w))
