"""
Sophi Bridge
Connects a compiled Sophi swap directly to Oneseam's HTLC coordination.

Usage:
    from sophi.bridge import execute_swap, settle_swap

    # 1. compile the .sph file
    result = compile_swap(parse(open("trade.sph").read()))

    # 2. execute — starts HTLC coordination in Oneseam
    swap = execute_swap(
        compiled   = result,
        match_id   = "match_abc123",
        client     = oneseam_client,   # the authenticated client dict
        oneseam    = oneseam_instance, # your Oneseam object
    )

    # 3. settle — submit proof after both sides fund
    receipt = settle_swap(
        swap_id  = swap["swap_id"],
        secret   = result.htlc_params["secret"],
        tx_hash  = "btc_tx_hash_here",
        client   = oneseam_client,
        oneseam  = oneseam_instance,
    )
"""

from typing import Any, Dict, Optional
from .compiler import CompiledSwap


# ── Execute ────────────────────────────────────────────────────────────────────

def execute_swap(
    compiled:  CompiledSwap,
    match_id:  str,
    client:    Dict[str, Any],
    oneseam:   Any,
    request_id: str = "",
) -> Dict[str, Any]:
    """
    Takes a compiled Sophi swap and starts HTLC coordination in Oneseam.

    Maps directly to:
        oneseam.start_htlc_coordination(client, match_id, request_id)

    Returns the swap dict from Oneseam (contains swap_id, status, htlc_a, htlc_b).
    """

    # Inject the Sophi secret_hash into the client context so Oneseam
    # picks it up inside _ensure_swap_for_match instead of generating a new one.
    # We pass it as a hint in the request_id field using a structured prefix,
    # OR you can patch client temporarily — depends on your Oneseam version.
    # The cleanest approach: add sophi metadata to client claims.

    client_with_sophi = {
        **client,
        "claims": {
            **(client.get("claims") or {}),
            "sophi": {
                "secret_hash":        compiled.htlc_params["secret_hash"],
                "expiration":         compiled.htlc_params["expiration"],
                "batch_allow_partial": compiled.htlc_params["batch_allow_partial"],
                "party_count":        compiled.htlc_params["party_count"],
                "htlc_legs":          compiled.htlc_params["htlc_legs"],
                "intents":            compiled.intents,
            }
        }
    }

    result = oneseam.start_htlc_coordination(
        client_with_sophi,
        match_id,
        request_id or f"sophi:{compiled.htlc_params['secret_hash'][:8]}",
    )

    # Attach the Sophi secret to the result so the caller can use it for settlement.
    # NEVER log or persist this — keep it in memory only.
    result["_sophi_secret"] = compiled.htlc_params["secret"]
    result["_sophi_secret_hash"] = compiled.htlc_params["secret_hash"]

    return result


# ── Settle ─────────────────────────────────────────────────────────────────────

def settle_swap(
    swap_id:    str,
    secret:     str,
    tx_hash:    str,
    client:     Dict[str, Any],
    oneseam:    Any,
    confirmations: int = 1,
    request_id: str = "",
) -> Dict[str, Any]:
    """
    Submits the HTLC proof to Oneseam after both sides have funded.

    Maps directly to:
        oneseam.submit_htlc_proof(client, swap_id, proof, request_id)

    The proof structure mirrors what submit_htlc_proof expects:
        - tx_hash:       the Bitcoin transaction hash
        - confirmations: number of confirmations
        - secret:        the preimage — Oneseam verifies sha256(secret) == secret_hash
    """

    proof = {
        "tx_hash":       tx_hash,
        "confirmations": confirmations,
        "secret":        secret,
    }

    return oneseam.submit_htlc_proof(
        client,
        swap_id,
        proof,
        request_id or f"sophi:settle:{swap_id[:8]}",
    )


# ── One-shot helper ────────────────────────────────────────────────────────────

def run_swap(
    sph_source:  str,
    match_id:    str,
    client:      Dict[str, Any],
    oneseam:     Any,
    tx_hash:     Optional[str] = None,
    confirmations: int = 1,
) -> Dict[str, Any]:
    """
    Full pipeline in one call:
        parse → verify → compile → execute → (optionally) settle

    If tx_hash is provided, also submits the proof.
    Returns the swap result dict.

    Example:
        result = run_swap(
            sph_source = open("trade.sph").read(),
            match_id   = "match_abc123",
            client     = my_client,
            oneseam    = my_oneseam,
        )
    """
    from .lexer import LexError
    from .parser import parse, ParseError
    from .verifier import verify, VerifyError
    from .compiler import compile_swap

    program  = parse(sph_source)
    warnings = verify(program)
    compiled = compile_swap(program, warnings)

    swap = execute_swap(
        compiled=compiled,
        match_id=match_id,
        client=client,
        oneseam=oneseam,
    )

    if tx_hash:
        swap["settlement"] = settle_swap(
            swap_id=swap["swap_id"],
            secret=compiled.htlc_params["secret"],
            tx_hash=tx_hash,
            client=client,
            oneseam=oneseam,
            confirmations=confirmations,
        )

    return swap
