import json
import sqlite3
from contextlib import contextmanager
from pathlib import Path

DB_FILE = Path.home() / ".taskr" / "tasks.db"
_LEGACY_JSON = Path.home() / ".taskr" / "tasks.json"


def _row_to_task(row: sqlite3.Row) -> dict:
    return {"id": row["id"], "text": row["text"], "done": bool(row["done"])}


@contextmanager
def _connect():
    DB_FILE.parent.mkdir(parents=True, exist_ok=True)
    conn = sqlite3.connect(DB_FILE)
    conn.row_factory = sqlite3.Row
    conn.execute("""
        CREATE TABLE IF NOT EXISTS tasks (
            id   INTEGER PRIMARY KEY AUTOINCREMENT,
            text TEXT    NOT NULL,
            done INTEGER NOT NULL DEFAULT 0
        )
    """)
    conn.commit()
    try:
        yield conn
    finally:
        conn.close()


def _migrate_from_json() -> None:
    """One-time import of tasks.json into SQLite. Renames the source to .bak on completion."""
    if not _LEGACY_JSON.exists() or DB_FILE.exists():
        return
    tasks = json.loads(_LEGACY_JSON.read_text())
    with _connect() as conn:
        for task in tasks:
            conn.execute(
                "INSERT INTO tasks (id, text, done) VALUES (?, ?, ?)",
                (task["id"], task["text"], int(task["done"])),
            )
        conn.commit()
    _LEGACY_JSON.rename(_LEGACY_JSON.with_suffix(".json.bak"))


def add_task(text: str) -> dict:
    _migrate_from_json()
    with _connect() as conn:
        cur = conn.execute("INSERT INTO tasks (text) VALUES (?)", (text,))
        conn.commit()
        row = conn.execute("SELECT * FROM tasks WHERE id = ?", (cur.lastrowid,)).fetchone()
    return _row_to_task(row)


def get_tasks() -> list[dict]:
    _migrate_from_json()
    with _connect() as conn:
        rows = conn.execute("SELECT * FROM tasks ORDER BY id").fetchall()
    return [_row_to_task(r) for r in rows]


def mark_done(number: int) -> dict | None:
    _migrate_from_json()
    with _connect() as conn:
        row = conn.execute("SELECT * FROM tasks WHERE id = ?", (number,)).fetchone()
        if row is None:
            return None
        conn.execute("UPDATE tasks SET done = 1 WHERE id = ?", (number,))
        conn.commit()
        row = conn.execute("SELECT * FROM tasks WHERE id = ?", (number,)).fetchone()
    return _row_to_task(row)


def delete_task(number: int) -> dict | None:
    _migrate_from_json()
    with _connect() as conn:
        row = conn.execute("SELECT * FROM tasks WHERE id = ?", (number,)).fetchone()
        if row is None:
            return None
        conn.execute("DELETE FROM tasks WHERE id = ?", (number,))
        conn.commit()
    return _row_to_task(row)
