import json
import os
import sqlite3
import uuid
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Dict, Optional

from fastapi import Depends, FastAPI, Header, HTTPException
from pydantic import BaseModel, Field

DB_PATH = Path(os.getenv("CLAN_CONSENT_DB_PATH", "/data/clan_consent.sqlite"))
API_KEY = os.getenv("CLAN_ADAPTER_API_KEY", "").strip()
VISIBILITY = {"public", "interclan", "incircle", "soulsafe", "sacred"}

app = FastAPI(title="CLAN Consent Adapter", version="1.0.0")


def _utc_now() -> str:
    return datetime.now(timezone.utc).isoformat()


def _connect() -> sqlite3.Connection:
    DB_PATH.parent.mkdir(parents=True, exist_ok=True)
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    return conn


def _init_db() -> None:
    conn = _connect()
    try:
        cur = conn.cursor()
        cur.execute(
            """
            CREATE TABLE IF NOT EXISTS consent_events (
                id TEXT PRIMARY KEY,
                circle TEXT,
                subject TEXT,
                method TEXT,
                signers_json TEXT,
                caveats TEXT,
                visibility_level TEXT,
                provenance_json TEXT,
                created_at TEXT NOT NULL
            )
            """
        )
        cur.execute(
            """
            CREATE TABLE IF NOT EXISTS testimony_drafts (
                id TEXT PRIMARY KEY,
                title TEXT,
                circle TEXT,
                visibility_level TEXT,
                content_json TEXT,
                status TEXT,
                provenance_json TEXT,
                consent_event_id TEXT,
                created_at TEXT NOT NULL,
                updated_at TEXT NOT NULL
            )
            """
        )
        conn.commit()
    finally:
        conn.close()


class ConsentCreate(BaseModel):
    circle: str
    subject: str = Field(description="decision/testimony/bridge/rights")
    method: str = "live_presence"
    signers: list[str] = Field(default_factory=list)
    caveats: Optional[str] = None
    visibility_level: str = "incircle"
    provenance: Dict[str, Any] = Field(default_factory=dict)


class TestimonyDraftCreate(BaseModel):
    title: str
    circle: str
    visibility_level: str = "incircle"
    content: Dict[str, Any] = Field(default_factory=dict)
    status: str = "draft"
    provenance: Dict[str, Any] = Field(default_factory=dict)
    consent_event_id: Optional[str] = None


def _auth(authorization: Optional[str] = Header(default=None)) -> None:
    if not API_KEY:
        return
    expected = f"Bearer {API_KEY}"
    if authorization != expected:
        raise HTTPException(status_code=401, detail="Unauthorized")


def _check_visibility(level: str) -> str:
    v = (level or "").strip().lower()
    if v not in VISIBILITY:
        raise HTTPException(status_code=400, detail=f"invalid visibility_level: {level}")
    return v


@app.on_event("startup")
def startup() -> None:
    _init_db()


@app.get("/health")
def health() -> Dict[str, Any]:
    return {"status": "ok", "service": "clan-consent-adapter"}


@app.post("/consent/events")
def create_consent_event(body: ConsentCreate, _: None = Depends(_auth)) -> Dict[str, Any]:
    cid = str(uuid.uuid4())
    visibility = _check_visibility(body.visibility_level)
    now = _utc_now()
    conn = _connect()
    try:
        cur = conn.cursor()
        cur.execute(
            """
            INSERT INTO consent_events(id, circle, subject, method, signers_json, caveats, visibility_level, provenance_json, created_at)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
            """,
            (
                cid,
                body.circle,
                body.subject,
                body.method,
                json.dumps(body.signers, ensure_ascii=False),
                body.caveats or "",
                visibility,
                json.dumps(body.provenance, ensure_ascii=False),
                now,
            ),
        )
        conn.commit()
    finally:
        conn.close()
    return {"consent_event_id": cid, "status": "confirmed", "visibility_level": visibility}


@app.get("/consent/events/{event_id}")
def get_consent_event(event_id: str, _: None = Depends(_auth)) -> Dict[str, Any]:
    conn = _connect()
    try:
        cur = conn.cursor()
        cur.execute("SELECT * FROM consent_events WHERE id = ?", (event_id,))
        row = cur.fetchone()
    finally:
        conn.close()
    if not row:
        raise HTTPException(status_code=404, detail="consent_event_not_found")
    return {
        "id": row["id"],
        "circle": row["circle"],
        "subject": row["subject"],
        "method": row["method"],
        "signers": json.loads(row["signers_json"] or "[]"),
        "caveats": row["caveats"],
        "visibility_level": row["visibility_level"],
        "provenance": json.loads(row["provenance_json"] or "{}"),
        "created_at": row["created_at"],
    }


@app.post("/testimony/drafts")
def create_testimony_draft(body: TestimonyDraftCreate, _: None = Depends(_auth)) -> Dict[str, Any]:
    tid = str(uuid.uuid4())
    visibility = _check_visibility(body.visibility_level)
    status = body.status if body.status in {"draft", "needs_confirmation", "confirmed"} else "draft"
    now = _utc_now()
    conn = _connect()
    try:
        cur = conn.cursor()
        cur.execute(
            """
            INSERT INTO testimony_drafts(id, title, circle, visibility_level, content_json, status, provenance_json, consent_event_id, created_at, updated_at)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            """,
            (
                tid,
                body.title,
                body.circle,
                visibility,
                json.dumps(body.content, ensure_ascii=False),
                status,
                json.dumps(body.provenance, ensure_ascii=False),
                body.consent_event_id,
                now,
                now,
            ),
        )
        conn.commit()
    finally:
        conn.close()
    return {"testimony_id": tid, "status": status, "visibility_level": visibility}


@app.get("/testimony/drafts/{testimony_id}")
def get_testimony_draft(testimony_id: str, _: None = Depends(_auth)) -> Dict[str, Any]:
    conn = _connect()
    try:
        cur = conn.cursor()
        cur.execute("SELECT * FROM testimony_drafts WHERE id = ?", (testimony_id,))
        row = cur.fetchone()
    finally:
        conn.close()
    if not row:
        raise HTTPException(status_code=404, detail="testimony_not_found")
    return {
        "id": row["id"],
        "title": row["title"],
        "circle": row["circle"],
        "visibility_level": row["visibility_level"],
        "content": json.loads(row["content_json"] or "{}"),
        "status": row["status"],
        "provenance": json.loads(row["provenance_json"] or "{}"),
        "consent_event_id": row["consent_event_id"],
        "created_at": row["created_at"],
        "updated_at": row["updated_at"],
    }
