from __future__ import annotations

import json
import sqlite3


class ReviewRepository:
    def watchlist(self, connection: sqlite3.Connection, user_id: int) -> tuple[sqlite3.Row, ...]:
        return tuple(
            connection.execute(
                """SELECT identifier, name, sector, remark, created_at FROM watchlist_entries
                WHERE user_id = ? ORDER BY created_at, identifier""",
                (user_id,),
            ).fetchall()
        )

    def save_watch(
        self, connection: sqlite3.Connection, user_id: int, item: dict, now: str
    ) -> None:
        connection.execute(
            """INSERT INTO watchlist_entries (user_id, identifier, name, sector, remark, created_at)
            VALUES (?, ?, ?, ?, ?, ?)
            ON CONFLICT(user_id, identifier) DO UPDATE SET
                name=excluded.name, sector=excluded.sector,
                remark=CASE
                    WHEN excluded.remark = '' THEN watchlist_entries.remark
                    ELSE excluded.remark
                END""",
            (
                user_id,
                item["identifier"],
                item["name"],
                item.get("sector"),
                item.get("remark") or "",
                now,
            ),
        )

    def delete_watch(self, connection: sqlite3.Connection, user_id: int, identifier: str) -> bool:
        cursor = connection.execute(
            "DELETE FROM watchlist_entries WHERE user_id = ? AND identifier = ?",
            (user_id, identifier),
        )
        return cursor.rowcount > 0

    def save_watch_remark(
        self, connection: sqlite3.Connection, user_id: int, identifier: str, remark: str
    ) -> bool:
        cursor = connection.execute(
            "UPDATE watchlist_entries SET remark=? WHERE user_id=? AND identifier=?",
            (remark, user_id, identifier),
        )
        return cursor.rowcount > 0

    def latest_factors(self, connection: sqlite3.Connection, through: str) -> dict[str, dict]:
        snapshot = connection.execute(
            """SELECT id, trade_date FROM screener_factor_snapshots
            WHERE trade_date <= ? ORDER BY trade_date DESC, id DESC LIMIT 1""",
            (through,),
        ).fetchone()
        if snapshot is None:
            return {}
        return {
            str(row["identifier"]): json.loads(str(row["payload_json"]))
            for row in connection.execute(
                "SELECT identifier, payload_json FROM screener_factor_values WHERE snapshot_id = ?",
                (int(snapshot["id"]),),
            ).fetchall()
        }

    def latest_auction_scores(
        self, connection: sqlite3.Connection, through: str
    ) -> dict[str, float]:
        row = connection.execute(
            """SELECT payload_json FROM market_insight_snapshots
            WHERE kind = 'auction' AND trade_date <= ? AND entity_key = ''
            ORDER BY trade_date DESC LIMIT 1""",
            (through,),
        ).fetchone()
        if row is None:
            return {}
        payload = json.loads(str(row["payload_json"]))
        scores = {}
        for key in ("_market_rows", "rows", "one_price_rows"):
            for item in payload.get(key) or []:
                identifier = str(item.get("identifier") or item.get("ts_code") or "")
                score = item.get("attention_score")
                if identifier and isinstance(score, (int, float)):
                    scores[identifier] = float(score)
        return scores

    def note(
        self, connection: sqlite3.Connection, user_id: int, code: str, trade_date: str
    ) -> sqlite3.Row | None:
        return connection.execute(
            "SELECT * FROM review_notes WHERE user_id = ? AND code = ? AND trade_date = ?",
            (user_id, code, trade_date),
        ).fetchone()

    def notes(
        self, connection: sqlite3.Connection, user_id: int, code: str = "", limit: int = 60
    ) -> tuple[sqlite3.Row, ...]:
        return tuple(
            connection.execute(
                """SELECT * FROM review_notes WHERE user_id = ? AND code = ?
                ORDER BY trade_date DESC, id DESC LIMIT ?""",
                (user_id, code, limit),
            ).fetchall()
        )

    def save_note(self, connection: sqlite3.Connection, user_id: int, data: dict, now: str) -> int:
        connection.execute(
            """INSERT INTO review_notes (
                user_id, code, stock_name, trade_date, summary, content, plan,
                created_at, updated_at
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
            ON CONFLICT(user_id, code, trade_date) DO UPDATE SET
                stock_name=excluded.stock_name, summary=excluded.summary,
                content=excluded.content, plan=excluded.plan, updated_at=excluded.updated_at""",
            (
                user_id,
                data["code"],
                data["stock_name"],
                data["trade_date"],
                data["summary"],
                data["content"],
                data["plan"],
                now,
                now,
            ),
        )
        row = self.note(connection, user_id, data["code"], data["trade_date"])
        if row is None:
            raise RuntimeError("复盘记录写入失败")
        return int(row["id"])

    def delete_note(self, connection: sqlite3.Connection, user_id: int, note_id: int) -> bool:
        cursor = connection.execute(
            "DELETE FROM review_notes WHERE user_id = ? AND id = ?", (user_id, note_id)
        )
        return cursor.rowcount > 0

    def trades(
        self, connection: sqlite3.Connection, user_id: int, limit: int = 300
    ) -> tuple[sqlite3.Row, ...]:
        return tuple(
            connection.execute(
                """SELECT * FROM trade_entries WHERE user_id = ?
                ORDER BY trade_date DESC, id DESC LIMIT ?""",
                (user_id, limit),
            ).fetchall()
        )

    def trade(
        self, connection: sqlite3.Connection, user_id: int, trade_id: int
    ) -> sqlite3.Row | None:
        return connection.execute(
            "SELECT * FROM trade_entries WHERE user_id = ? AND id = ?", (user_id, trade_id)
        ).fetchone()

    def save_trade(self, connection: sqlite3.Connection, user_id: int, data: dict, now: str) -> int:
        values = (
            data["trade_date"],
            data["code"],
            data["name"],
            data["action"],
            data["price"],
            data["quantity"],
            data["position_pct"],
            data["pnl_amount"],
            data["pnl_pct"],
            data["emotion"],
            json.dumps(data["tags"], ensure_ascii=False),
            data["thesis"],
            data["execution"],
            now,
        )
        if data.get("id"):
            cursor = connection.execute(
                """UPDATE trade_entries SET trade_date=?, code=?, name=?, action=?, price=?,
                quantity=?, position_pct=?, pnl_amount=?, pnl_pct=?, emotion=?, tags_json=?,
                thesis=?, execution=?, updated_at=? WHERE user_id=? AND id=?""",
                (*values, user_id, int(data["id"])),
            )
            if cursor.rowcount == 0:
                raise ValueError("交易记录不存在或无权修改。")
            return int(data["id"])
        cursor = connection.execute(
            """INSERT INTO trade_entries (
                trade_date, code, name, action, price, quantity, position_pct, pnl_amount,
                pnl_pct, emotion, tags_json, thesis, execution, created_at, updated_at, user_id
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
            (*values, now, user_id),
        )
        return int(cursor.lastrowid)

    def delete_trade(self, connection: sqlite3.Connection, user_id: int, trade_id: int) -> bool:
        cursor = connection.execute(
            "DELETE FROM trade_entries WHERE user_id = ? AND id = ?", (user_id, trade_id)
        )
        return cursor.rowcount > 0

    def save_alert(self, connection: sqlite3.Connection, user_id: int, data: dict, now: str) -> int:
        connection.execute(
            """INSERT INTO alerts (
                user_id, kind, title, content, available_date, code, dedupe_key,
                created_at, updated_at
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
            ON CONFLICT(user_id, dedupe_key) DO NOTHING""",
            (
                user_id,
                data["kind"],
                data["title"],
                data["content"],
                data["available_date"],
                data["code"],
                data["dedupe_key"],
                now,
                now,
            ),
        )
        row = connection.execute(
            "SELECT id FROM alerts WHERE user_id = ? AND dedupe_key = ?",
            (user_id, data["dedupe_key"]),
        ).fetchone()
        return int(row["id"])

    def alerts(
        self, connection: sqlite3.Connection, user_id: int, unread: bool
    ) -> tuple[sqlite3.Row, ...]:
        clause = "AND is_read = 0" if unread else ""
        return tuple(
            connection.execute(
                f"""SELECT * FROM alerts WHERE user_id = ? {clause}
                ORDER BY available_date > date('now'), is_read,
                available_date DESC, id DESC LIMIT 100""",
                (user_id,),
            ).fetchall()
        )

    def unread_count(self, connection: sqlite3.Connection, user_id: int, today: str) -> int:
        row = connection.execute(
            """SELECT COUNT(*) total FROM alerts
            WHERE user_id = ? AND available_date <= ? AND is_read = 0""",
            (user_id, today),
        ).fetchone()
        return int(row["total"])

    def mark_alert(
        self, connection: sqlite3.Connection, user_id: int, alert_id: int, now: str
    ) -> bool:
        cursor = connection.execute(
            "UPDATE alerts SET is_read=1, read_at=?, updated_at=? WHERE user_id=? AND id=?",
            (now, now, user_id, alert_id),
        )
        return cursor.rowcount > 0

    def mark_all_alerts(
        self, connection: sqlite3.Connection, user_id: int, today: str, now: str
    ) -> int:
        cursor = connection.execute(
            """UPDATE alerts SET is_read=1, read_at=?, updated_at=?
            WHERE user_id=? AND available_date <= ? AND is_read=0""",
            (now, now, user_id, today),
        )
        return int(cursor.rowcount)

    def delete_alert(self, connection: sqlite3.Connection, user_id: int, alert_id: int) -> bool:
        cursor = connection.execute(
            "DELETE FROM alerts WHERE user_id=? AND id=?", (user_id, alert_id)
        )
        return cursor.rowcount > 0

    def messages(
        self, connection: sqlite3.Connection, user_id: int, limit: int = 100
    ) -> tuple[sqlite3.Row, ...]:
        rows = connection.execute(
            """SELECT * FROM review_assistant_messages WHERE user_id=?
            ORDER BY id DESC LIMIT ?""",
            (user_id, limit),
        ).fetchall()
        return tuple(reversed(rows))

    def add_message(
        self, connection: sqlite3.Connection, user_id: int, data: dict, now: str
    ) -> None:
        connection.execute(
            """INSERT INTO review_assistant_messages
            (user_id, role, content, context_date, request_id, status, created_at)
            VALUES (?, ?, ?, ?, ?, ?, ?)""",
            (
                user_id,
                data["role"],
                data["content"],
                data["context_date"],
                data.get("request_id"),
                data["status"],
                now,
            ),
        )

    def clear_messages(self, connection: sqlite3.Connection, user_id: int) -> int:
        cursor = connection.execute(
            "DELETE FROM review_assistant_messages WHERE user_id=?", (user_id,)
        )
        return int(cursor.rowcount)
