"""SQLite translation storage."""

import hashlib
import json
import sqlite3
from datetime import datetime, timezone
from pathlib import Path


def _content_hash(source_text: str, project_context_hash: str, string_context_hash: str) -> str:
    return hashlib.sha256(
        (source_text + "\x00" + project_context_hash + "\x00" + string_context_hash).encode()
    ).hexdigest()


class TranslationStore:
    def __init__(self, db_path: Path):
        self._db_path = Path(db_path)
        self._conn: sqlite3.Connection | None = None

    def initialize(self):
        self._db_path.parent.mkdir(parents=True, exist_ok=True)
        self._conn = sqlite3.connect(str(self._db_path), check_same_thread=False)
        self._conn.execute("PRAGMA journal_mode=WAL")
        self._conn.execute("""
            CREATE TABLE IF NOT EXISTS translations (
                source_lang TEXT NOT NULL,
                target_lang TEXT NOT NULL,
                content_hash TEXT NOT NULL,
                plural_category TEXT NOT NULL DEFAULT '',
                source_text TEXT NOT NULL,
                translated_text TEXT NOT NULL,
                model TEXT NOT NULL,
                status TEXT NOT NULL,
                created_at TEXT NOT NULL,
                project_context_hash TEXT NOT NULL,
                string_context_hash TEXT NOT NULL,
                string_context TEXT NOT NULL DEFAULT '',
                PRIMARY KEY (source_lang, target_lang, content_hash, plural_category)
            )
        """)
        self._conn.commit()

    def _get_conn(self) -> sqlite3.Connection:
        if self._conn is None:
            raise RuntimeError("Store not initialized")
        return self._conn

    def lookup(
        self,
        source_text: str,
        source_lang: str,
        target_lang: str,
        project_context_hash: str,
        string_context_hash: str,
    ) -> str | None:
        conn = self._get_conn()
        chash = _content_hash(source_text, project_context_hash, string_context_hash)
        row = conn.execute(
            "SELECT translated_text FROM translations WHERE source_lang=? AND target_lang=? AND content_hash=? AND plural_category='' AND status='translated'",
            (source_lang, target_lang, chash),
        ).fetchone()
        return row[0] if row else None

    def insert(
        self,
        source_text: str,
        source_lang: str,
        target_lang: str,
        project_context_hash: str,
        string_context_hash: str,
        translated_text: str,
        model: str,
        status: str = "translated",
        string_context: str = "",
    ):
        conn = self._get_conn()
        chash = _content_hash(source_text, project_context_hash, string_context_hash)
        conn.execute(
            """INSERT OR IGNORE INTO translations
               (source_lang, target_lang, content_hash, plural_category, source_text, translated_text, model, status, created_at, project_context_hash, string_context_hash, string_context)
               VALUES (?, ?, ?, '', ?, ?, ?, ?, ?, ?, ?, ?)""",
            (source_lang, target_lang, chash, source_text, translated_text, model, status,
             datetime.now(timezone.utc).isoformat(), project_context_hash, string_context_hash, string_context or ""),
        )
        conn.commit()

    def lookup_plural(
        self,
        source_text: str,
        source_lang: str,
        target_lang: str,
        project_context_hash: str,
        string_context_hash: str,
    ) -> dict[str, str]:
        conn = self._get_conn()
        chash = _content_hash(source_text, project_context_hash, string_context_hash)
        rows = conn.execute(
            "SELECT plural_category, translated_text FROM translations WHERE source_lang=? AND target_lang=? AND content_hash=? AND plural_category!='' AND status='translated'",
            (source_lang, target_lang, chash),
        ).fetchall()
        return {row[0]: row[1] for row in rows}

    def insert_plural(
        self,
        source_text: str,
        source_lang: str,
        target_lang: str,
        project_context_hash: str,
        string_context_hash: str,
        plural_category: str,
        translated_text: str,
        model: str,
        status: str = "translated",
        string_context: str = "",
    ):
        conn = self._get_conn()
        chash = _content_hash(source_text, project_context_hash, string_context_hash)
        conn.execute(
            """INSERT OR IGNORE INTO translations
               (source_lang, target_lang, content_hash, plural_category, source_text, translated_text, model, status, created_at, project_context_hash, string_context_hash, string_context)
               VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
            (source_lang, target_lang, chash, plural_category, source_text, translated_text, model, status,
             datetime.now(timezone.utc).isoformat(), project_context_hash, string_context_hash, string_context or ""),
        )
        conn.commit()

    def stats(self) -> dict:
        conn = self._get_conn()
        rows = conn.execute(
            "SELECT target_lang, status, COUNT(*) FROM translations GROUP BY target_lang, status"
        ).fetchall()
        total = 0
        failed = 0
        by_language: dict[str, int] = {}
        for target_lang, status, count in rows:
            if status == "translated":
                total += count
                by_language[target_lang] = by_language.get(target_lang, 0) + count
            elif status == "failed":
                failed += count
        return {
            "total_translations": total,
            "total_failed": failed,
            "by_language": by_language,
        }

    def count(self, target_lang: str | None = None, failed_only: bool = False) -> int:
        conn = self._get_conn()
        sql = "SELECT COUNT(*) FROM translations WHERE 1=1"
        params: list = []
        if target_lang:
            sql += " AND target_lang=?"
            params.append(target_lang)
        if failed_only:
            sql += " AND status='failed'"
        return conn.execute(sql, params).fetchone()[0]

    def delete(self, target_lang: str | None = None, failed_only: bool = False) -> int:
        conn = self._get_conn()
        sql = "DELETE FROM translations WHERE 1=1"
        params: list = []
        if target_lang:
            sql += " AND target_lang=?"
            params.append(target_lang)
        if failed_only:
            sql += " AND status='failed'"
        cursor = conn.execute(sql, params)
        conn.commit()
        return cursor.rowcount

    def close(self):
        if self._conn is not None:
            self._conn.close()
            self._conn = None
