"""SQLite CRUD helpers for posts and post authors."""

from __future__ import annotations

import json
import time
import uuid
from typing import Any, Optional

from .schema import get_db


# ──────────────────────────────────────────────
# Posts
# ──────────────────────────────────────────────

def upsert_post(
    post_id: str,
    *,
    author_linkedin_id: str = "",
    author_name: str = "",
    text: str = "",
    metrics_json: str = "",
    source: str = "search",
) -> str:
    """Insert or update a post. Returns the internal row ID.

    If the post_id already exists, updates last_seen_at and metrics_json.
    Also upserts the post author if author_linkedin_id is provided.
    """
    now = int(time.time())
    db = get_db()

    row = db.execute(
        "SELECT id FROM posts WHERE post_id = ?", (post_id,)
    ).fetchone()

    if row:
        # Update existing
        db.execute(
            "UPDATE posts SET last_seen_at = ?, metrics_json = ? WHERE post_id = ?",
            (now, metrics_json or None, post_id),
        )
        db.commit()
        db.close()
        row_id = row["id"]
    else:
        # Insert new
        row_id = uuid.uuid4().hex[:12]
        db.execute(
            """INSERT INTO posts
               (id, post_id, author_linkedin_id, author_name, text, metrics_json,
                source, first_seen_at, last_seen_at)
               VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
            (row_id, post_id, author_linkedin_id or None, author_name or None,
             text[:2000] if text else None, metrics_json or None,
             source, now, now),
        )
        db.commit()
        db.close()

    # Upsert author if we have an ID
    if author_linkedin_id:
        upsert_post_author(
            linkedin_id=author_linkedin_id,
            name=author_name,
        )

    return row_id


def get_post(post_id: str) -> Optional[dict]:
    """Get a post by LinkedIn post URN."""
    db = get_db()
    row = db.execute("SELECT * FROM posts WHERE post_id = ?", (post_id,)).fetchone()
    db.close()
    return dict(row) if row else None


def list_posts(
    *,
    author_linkedin_id: str | None = None,
    topic: str | None = None,
    source: str | None = None,
    limit: int = 50,
    offset: int = 0,
) -> list[dict]:
    """List posts with optional filters."""
    conditions: list[str] = []
    params: list[Any] = []

    if author_linkedin_id:
        conditions.append("author_linkedin_id = ?")
        params.append(author_linkedin_id)
    if topic:
        conditions.append("topic = ?")
        params.append(topic)
    if source:
        conditions.append("source = ?")
        params.append(source)

    where = " AND ".join(conditions) if conditions else "1=1"
    db = get_db()
    rows = db.execute(
        f"SELECT * FROM posts WHERE {where} ORDER BY last_seen_at DESC LIMIT ? OFFSET ?",
        params + [limit, offset],
    ).fetchall()
    db.close()
    return [dict(r) for r in rows]


def get_unanalyzed_posts(limit: int = 20) -> list[dict]:
    """Get posts that haven't been analyzed yet (topic IS NULL)."""
    db = get_db()
    rows = db.execute(
        "SELECT * FROM posts WHERE topic IS NULL AND text IS NOT NULL "
        "ORDER BY last_seen_at DESC LIMIT ?",
        (limit,),
    ).fetchall()
    db.close()
    return [dict(r) for r in rows]


def update_post_analysis(post_id: str, topic: str, analysis_json: str) -> None:
    """Update a post's topic and analysis results."""
    db = get_db()
    db.execute(
        "UPDATE posts SET topic = ?, analysis_json = ? WHERE post_id = ?",
        (topic, analysis_json, post_id),
    )
    db.commit()
    db.close()


def is_post_known(post_id: str) -> bool:
    """Check if a post_id exists in the posts table."""
    db = get_db()
    row = db.execute(
        "SELECT 1 FROM posts WHERE post_id = ? LIMIT 1", (post_id,)
    ).fetchone()
    db.close()
    return row is not None


def get_posts_by_author(author_linkedin_id: str, limit: int = 20) -> list[dict]:
    """Get posts by a specific author."""
    db = get_db()
    rows = db.execute(
        "SELECT * FROM posts WHERE author_linkedin_id = ? ORDER BY last_seen_at DESC LIMIT ?",
        (author_linkedin_id, limit),
    ).fetchall()
    db.close()
    return [dict(r) for r in rows]


# ──────────────────────────────────────────────
# Post Authors
# ──────────────────────────────────────────────

def upsert_post_author(
    linkedin_id: str,
    *,
    name: str = "",
    headline: str = "",
    company: str = "",
) -> None:
    """Insert or update a post author. Increments posts_seen on update."""
    now = int(time.time())
    db = get_db()

    row = db.execute(
        "SELECT linkedin_id, posts_seen FROM post_authors WHERE linkedin_id = ?",
        (linkedin_id,),
    ).fetchone()

    if row:
        updates = ["posts_seen = posts_seen + 1", "last_post_at = ?"]
        params: list[Any] = [now]
        if name:
            updates.append("name = ?")
            params.append(name)
        if headline:
            updates.append("headline = ?")
            params.append(headline)
        if company:
            updates.append("company = ?")
            params.append(company)
        params.append(linkedin_id)
        db.execute(
            f"UPDATE post_authors SET {', '.join(updates)} WHERE linkedin_id = ?",
            params,
        )
    else:
        db.execute(
            """INSERT INTO post_authors
               (linkedin_id, name, headline, company, posts_seen, first_seen_at, last_post_at)
               VALUES (?, ?, ?, ?, 1, ?, ?)""",
            (linkedin_id, name or None, headline or None, company or None, now, now),
        )

    db.commit()
    db.close()

    # Auto-link to contact if one exists with this linkedin_id
    _auto_link_contact(linkedin_id)


def _auto_link_contact(linkedin_id: str) -> None:
    """If a contact exists with this linkedin_id, link the author to it."""
    db = get_db()
    contact_row = db.execute(
        "SELECT id FROM contacts WHERE linkedin_id = ? LIMIT 1",
        (linkedin_id,),
    ).fetchone()
    if contact_row:
        db.execute(
            "UPDATE post_authors SET contact_id = ? WHERE linkedin_id = ? AND contact_id IS NULL",
            (contact_row["id"], linkedin_id),
        )
        db.commit()
    db.close()


def get_post_author(linkedin_id: str) -> Optional[dict]:
    """Get a post author by LinkedIn ID."""
    db = get_db()
    row = db.execute(
        "SELECT * FROM post_authors WHERE linkedin_id = ?", (linkedin_id,)
    ).fetchone()
    db.close()
    return dict(row) if row else None


def list_post_authors(
    *,
    company: str | None = None,
    limit: int = 50,
    offset: int = 0,
) -> list[dict]:
    """List post authors with optional filters."""
    conditions: list[str] = []
    params: list[Any] = []

    if company:
        conditions.append("company = ?")
        params.append(company)

    where = " AND ".join(conditions) if conditions else "1=1"
    db = get_db()
    rows = db.execute(
        f"SELECT * FROM post_authors WHERE {where} ORDER BY last_post_at DESC LIMIT ? OFFSET ?",
        params + [limit, offset],
    ).fetchall()
    db.close()
    return [dict(r) for r in rows]


def link_author_to_contact(linkedin_id: str, contact_id: str) -> None:
    """Manually link a post author to a contact."""
    db = get_db()
    db.execute(
        "UPDATE post_authors SET contact_id = ? WHERE linkedin_id = ?",
        (contact_id, linkedin_id),
    )
    db.commit()
    db.close()


def update_author_topics(linkedin_id: str, topics: list[str]) -> None:
    """Update the accumulated topics list for an author."""
    db = get_db()
    # Merge with existing topics
    row = db.execute(
        "SELECT topics_json FROM post_authors WHERE linkedin_id = ?",
        (linkedin_id,),
    ).fetchone()
    if row:
        existing = []
        try:
            existing = json.loads(row["topics_json"] or "[]")
        except (json.JSONDecodeError, TypeError):
            pass
        merged = list(dict.fromkeys(existing + topics))[:20]  # Dedupe, cap at 20
        db.execute(
            "UPDATE post_authors SET topics_json = ? WHERE linkedin_id = ?",
            (json.dumps(merged), linkedin_id),
        )
        db.commit()
    db.close()


def find_known_authors(linkedin_ids: list[str]) -> list[dict]:
    """Batch check which authors are already tracked."""
    if not linkedin_ids:
        return []
    placeholders = ",".join("?" for _ in linkedin_ids)
    db = get_db()
    rows = db.execute(
        f"SELECT * FROM post_authors WHERE linkedin_id IN ({placeholders})",
        linkedin_ids,
    ).fetchall()
    db.close()
    return [dict(r) for r in rows]
