"""Trade journal — append-only JSONL store with interactive entry prompt."""
from __future__ import annotations

import json
from dataclasses import asdict, dataclass
from datetime import datetime, timezone
from pathlib import Path


@dataclass
class TradeEntry:
    ts: str                 # ISO timestamp of trade entry
    direction: str          # BUY or SELL
    symbol: str             # e.g. US30
    entry: float
    sl: float
    tp1: float | None
    tp2: float | None
    exit: float | None
    outcome: str            # "open"|"tp1"|"tp2"|"sl"|"manual"
    detected_ts: str | None
    notes: str = ""


class Journal:
    def __init__(self, path: Path) -> None:
        self.path = Path(path)
        self.path.parent.mkdir(parents=True, exist_ok=True)

    def add(self, entry: TradeEntry) -> None:
        with self.path.open("a", encoding="utf-8") as fh:
            json.dump(asdict(entry), fh)
            fh.write("\n")
            fh.flush()

    def all(self) -> list[TradeEntry]:
        if not self.path.exists():
            return []
        entries: list[TradeEntry] = []
        with self.path.open("r", encoding="utf-8") as fh:
            for line in fh:
                stripped = line.strip()
                if stripped:
                    entries.append(TradeEntry(**json.loads(stripped)))
        return entries


def prompt_entry(
    input_fn=input,
    detected: dict | None = None,
) -> TradeEntry:
    """Prompt user for a trade entry, using detected values as defaults."""
    d = detected or {}

    def ask(prompt: str, default: str | None = None) -> str:
        if default is not None:
            raw = input_fn(f"{prompt} [{default}]: ")
            return raw.strip() if raw.strip() else default
        return input_fn(f"{prompt}: ").strip()

    def ask_opt(prompt: str) -> str:
        return input_fn(f"{prompt} (blank=none): ").strip()

    ts = ask("Timestamp (ISO)", datetime.now(timezone.utc).isoformat())
    direction = ask("Direction BUY/SELL", d.get("direction", "BUY")).upper()
    symbol = ask("Symbol", d.get("symbol", "US30")).upper()
    entry = float(ask("Entry price"))
    sl = float(ask("Stop loss"))
    tp1_raw = ask_opt("TP1")
    tp2_raw = ask_opt("TP2")
    exit_raw = ask_opt("Exit price")
    outcome = ask("Outcome open/tp1/tp2/sl/manual", "open")
    detected_ts: str | None = d.get("detected_ts")
    notes = ask("Notes", "")

    return TradeEntry(
        ts=ts,
        direction=direction,
        symbol=symbol,
        entry=entry,
        sl=sl,
        tp1=float(tp1_raw) if tp1_raw else None,
        tp2=float(tp2_raw) if tp2_raw else None,
        exit=float(exit_raw) if exit_raw else None,
        outcome=outcome,
        detected_ts=detected_ts,
        notes=notes,
    )
