"""Unified schema module for GreyMatter.

Provides both SQLite and CockroachDB DDL for all table groups.
Each submodule covers one logical domain and exposes get_sqlite_ddl()
and get_crdb_ddl() functions.

Schema domains:
    core        — patterns, knowledge, work items, sessions (shared)
    cognitive   — observations, memory (Solo-only, NEVER syncs)
    distributed — agents, worktrees, work queue (legacy, kept for compat)
    teams       — members, folder scoping, auth (Teams-only)
    solo        — local work queue, agent sessions (Solo-only)
    salesos     — SalesOS domain tables
    twin        — Twin Arena tables

Usage:
    from greymatter_core.schema import get_solo_schema, get_teams_schema
    ddl = get_solo_schema()    # for Solo mode (core + cognitive + solo)
    ddl = get_teams_schema()   # for Teams mode (core + distributed + teams)
"""
from __future__ import annotations

from typing import Callable

SCHEMA_VERSION = "1.0"

# Lazy imports to avoid circular deps — modules register on first access
_modules: list[tuple[str, Callable[[], str], Callable[[], str]]] = []


def _ensure_loaded() -> None:
    """Load all schema submodules on first access."""
    if _modules:
        return
    from . import core, cognitive, distributed, solo, teams, team_cognitive, salesos, twin
    _modules.extend([
        ("core", core.get_sqlite_ddl, core.get_crdb_ddl),
        ("cognitive", cognitive.get_sqlite_ddl, cognitive.get_crdb_ddl),
        ("distributed", distributed.get_sqlite_ddl, distributed.get_crdb_ddl),
        ("solo", solo.get_sqlite_ddl, solo.get_crdb_ddl),
        ("teams", teams.get_sqlite_ddl, teams.get_crdb_ddl),
        ("team_cognitive", team_cognitive.get_sqlite_ddl, team_cognitive.get_crdb_ddl),
        ("salesos", salesos.get_sqlite_ddl, salesos.get_crdb_ddl),
        ("twin", twin.get_sqlite_ddl, twin.get_crdb_ddl),
    ])


def get_full_sqlite_schema() -> str:
    """Return combined SQLite DDL for all modules."""
    _ensure_loaded()
    parts = [f"-- Schema module: {name}" for name, _, _ in _modules]
    return "\n\n".join(
        f"-- Schema module: {name}\n{sqlite_fn()}"
        for name, sqlite_fn, _ in _modules
    )


def get_full_crdb_schema() -> str:
    """Return combined CockroachDB DDL for all modules."""
    _ensure_loaded()
    return "\n\n".join(
        f"-- Schema module: {name}\n{crdb_fn()}"
        for name, _, crdb_fn in _modules
    )


def get_module_names() -> list[str]:
    """Return list of registered schema module names."""
    _ensure_loaded()
    return [name for name, _, _ in _modules]


# ─── Product-Specific Schema Accessors ─────────────────────

_SOLO_MODULES = {"core", "cognitive", "solo"}
_TEAMS_MODULES = {"core", "distributed", "teams", "team_cognitive"}


def get_solo_schema() -> str:
    """Return SQLite DDL for Solo mode (core + cognitive + solo).

    This is the schema for a standalone developer installation.
    Cognitive memory stays local. No distributed/teams tables.
    """
    _ensure_loaded()
    return "\n\n".join(
        f"-- Schema module: {name}\n{sqlite_fn()}"
        for name, sqlite_fn, _ in _modules
        if name in _SOLO_MODULES
    )


def get_teams_schema(dialect: str = "sqlite") -> str:
    """Return DDL for Teams mode (core + distributed + teams).

    Args:
        dialect: "sqlite" for libsql/sqld, "crdb" for CockroachDB.

    Teams does NOT include cognitive tables — personal memory
    stays on the Solo instance and never syncs.
    """
    _ensure_loaded()
    if dialect == "crdb":
        return "\n\n".join(
            f"-- Schema module: {name}\n{crdb_fn()}"
            for name, _, crdb_fn in _modules
            if name in _TEAMS_MODULES
        )
    return "\n\n".join(
        f"-- Schema module: {name}\n{sqlite_fn()}"
        for name, sqlite_fn, _ in _modules
        if name in _TEAMS_MODULES
    )
