"""Orchestrator: parse → scrape → chunk → embed → store in LanceDB."""

import logging

import pyarrow as pa

from ars25.core.config import get_settings
from ars25.core.db import get_connection, table_exists, reset_connection
from ars25.ingestion.csv_parser import load_csv
from ars25.ingestion.chunker import chunk_statute
from ars25.ingestion.scraper import scrape_all
from ars25.ingestion.embedder import embed_texts
from ars25.models.statute import StatuteChunk

logger = logging.getLogger(__name__)


def _build_arrow_table(chunks: list[StatuteChunk]) -> pa.Table:
    """Convert chunks to a PyArrow table for LanceDB."""
    return pa.table({
        "section": [c.section for c in chunks],
        "title": [c.title for c in chunks],
        "chapter_number": [c.chapter_number for c in chunks],
        "chapter_title": [c.chapter_title for c in chunks],
        "article_number": [c.article_number for c in chunks],
        "article_title": [c.article_title for c in chunks],
        "url": [c.url for c in chunks],
        "chunk_index": [c.chunk_index for c in chunks],
        "text": [c.chunk_text for c in chunks],
        "vector": [c.vector for c in chunks],
    })


async def run_ingestion(force: bool = False) -> dict:
    """Run the full ingestion pipeline.

    Returns a summary dict with counts and status.
    """
    settings = get_settings()

    # Check if DB already exists
    if not force and table_exists():
        return {
            "skipped": True,
            "reason": "Database already exists. Use force=True to rebuild.",
        }

    # Step 1: Parse CSV
    logger.info("Step 1: Parsing CSV from %s", settings.csv_path)
    records = load_csv(settings.csv_path)
    logger.info("Found %d statute records", len(records))

    # Step 2: Scrape HTML
    logger.info("Step 2: Scraping statute text from azleg.gov...")
    urls = {r.section: r.url for r in records}
    scraped = await scrape_all(
        urls,
        concurrency=settings.scrape_concurrency,
    )
    logger.info("Scraped %d/%d statutes", len(scraped), len(records))

    # Step 3: Chunk
    logger.info("Step 3: Chunking statutes...")
    all_chunks: list[StatuteChunk] = []
    for record in records:
        text = scraped.get(record.section, "")
        if not text:
            continue
        record.full_text = text
        chunks = chunk_statute(record, text)
        all_chunks.extend(chunks)
    logger.info("Created %d chunks from %d statutes", len(all_chunks), len(scraped))

    if not all_chunks:
        return {"error": "No chunks created — scraping may have failed entirely."}

    # Step 4: Embed
    logger.info("Step 4: Embedding %d chunks...", len(all_chunks))
    texts = [c.chunk_text for c in all_chunks]
    vectors = embed_texts(texts)
    for chunk, vec in zip(all_chunks, vectors):
        chunk.vector = vec
    logger.info("Embedding complete")

    # Step 5: Store in LanceDB
    logger.info("Step 5: Writing to LanceDB at %s", settings.db_path)
    conn = get_connection()

    # Drop existing table if present
    if settings.table_name in conn.table_names():
        conn.drop_table(settings.table_name)
        logger.info("Dropped existing table '%s'", settings.table_name)

    arrow_table = _build_arrow_table(all_chunks)
    table = conn.create_table(settings.table_name, arrow_table)
    logger.info("Created table '%s' with %d rows", settings.table_name, len(all_chunks))

    # Step 6: Create FTS index
    logger.info("Step 6: Creating full-text search index...")
    fts_ok = False
    try:
        table.create_fts_index("text")
        fts_ok = True
        logger.info("FTS index created on 'text' column")
    except Exception as e:
        logger.warning("FTS index creation failed: %s — vector-only search will be used", e)

    # Reset connection so subsequent queries see the new table
    reset_connection()

    return {
        "skipped": False,
        "statutes_scraped": len(scraped),
        "statutes_total": len(records),
        "chunks_created": len(all_chunks),
        "fts_index": fts_ok,
        "db_path": settings.db_path,
    }
