"""Parse and store .eaf files into the corpus database."""

from __future__ import annotations

import logging
import os
import sqlite3
from pathlib import Path

from sltk.db import queries as Q
from sltk.io.elan import get_eaf_metadata
from sltk.io.elan_roundtrip import ElanDocument

_logger = logging.getLogger(__name__)


def _sec_to_ms(sec: float) -> int:
    return round(sec * 1000)


def parse_and_store_eaf(
    conn: sqlite3.Connection,
    path: str | Path,
    source: str = "file",
) -> bool:
    """Parse an .eaf file and store its contents in the DB.

    Returns ``True`` if the file was (re-)ingested, ``False`` if skipped
    because the mtime has not changed.
    """
    path = Path(path)
    if not path.exists():
        _logger.warning("File not found, skipping: %s", path)
        return False

    file_mtime = os.path.getmtime(path)
    path_str = str(path)

    # Check if already up-to-date
    row = conn.execute(Q.FILE_BY_PATH, (path_str,)).fetchone()
    if row is not None:
        existing_mtime = row[1]
        if existing_mtime == file_mtime:
            return False
        # File changed — delete old data (CASCADE handles children)
        conn.execute(Q.DELETE_FILE, (path_str,))

    # Parse with ElanDocument for tier/segment data
    try:
        doc = ElanDocument.open(path)
    except Exception as exc:
        _logger.warning("Skipping unparseable EAF: %s (%s)", path, exc)
        return False

    # Get metadata via elan.py helper (author, date, media refs)
    try:
        meta = get_eaf_metadata(path)
    except Exception:
        meta = {"author": None, "date": None, "media_files": []}

    tiers = doc.get_tiers()
    segments = doc.get_segments()

    # Insert file row
    cur = conn.execute(
        Q.INSERT_FILE,
        (
            path_str,
            path.name,
            path.stem,
            meta.get("author"),
            meta.get("date"),
            file_mtime,
            len(segments),
        ),
    )
    file_id = cur.lastrowid

    # Insert media refs
    for mf in meta.get("media_files", []):
        conn.execute(
            Q.INSERT_MEDIA_REF,
            (
                file_id,
                mf.get("url"),
                mf.get("mime_type"),
                mf.get("relative_url"),
            ),
        )

    # Insert tiers and build tier_id -> rowid map
    tier_rowid_map: dict[str, int] = {}
    for ti in tiers:
        cur = conn.execute(
            Q.INSERT_TIER,
            (
                file_id,
                ti.name,
                ti.linguistic_type,
                ti.participant,
                ti.annotator,
                None,  # parent_ref not exposed by ElanDocument
            ),
        )
        tier_rowid_map[ti.name] = cur.lastrowid  # type: ignore[assignment]

    # Insert segments
    for seg in segments:
        tier_rowid = tier_rowid_map.get(seg.tier)
        if tier_rowid is None:
            continue
        conn.execute(
            Q.INSERT_SEGMENT,
            (
                file_id,
                tier_rowid,
                seg.annotation_id,
                _sec_to_ms(seg.start),
                _sec_to_ms(seg.end),
                seg.label if seg.label else None,
                None,  # confidence
                source,
            ),
        )

    # Auto-tag file source when ingesting model outputs
    if source == "model":
        conn.execute(
            "INSERT OR REPLACE INTO file_metadata "
            "(file_id, key, value, source) "
            "VALUES (?, 'annotation_source', 'model', 'system')",
            (file_id,),
        )

    return True
