import json
from dataclasses import dataclass
from pathlib import Path

from cascade.exporters.json_exporter import JSONFileExporter


@dataclass
class _SpanContext:
    trace_id: int
    span_id: int


@dataclass
class _StatusCode:
    name: str


@dataclass
class _Status:
    status_code: _StatusCode
    description: str = ""


@dataclass
class _Kind:
    name: str


@dataclass
class _Parent:
    span_id: int


class _ReadableSpan:
    def __init__(self, *, trace_id: int, span_id: int, name: str, start_time: int, end_time: int):
        self._ctx = _SpanContext(trace_id=trace_id, span_id=span_id)
        self.parent = _Parent(span_id=0xABC)
        self.name = name
        self.kind = _Kind(name="INTERNAL")
        self.start_time = start_time
        self.end_time = end_time
        self.status = _Status(status_code=_StatusCode(name="OK"))
        self.attributes = {"k": "v"}
        self.events = []

    def get_span_context(self):
        return self._ctx


def test_json_exporter_creates_file_and_appends_spans(tmp_path: Path):
    out = tmp_path / "traces" / "out.json"
    exporter = JSONFileExporter(str(out))

    spans = [
        _ReadableSpan(trace_id=1, span_id=2, name="a", start_time=1, end_time=2),
        _ReadableSpan(trace_id=1, span_id=3, name="b", start_time=3, end_time=4),
    ]
    res = exporter.export(spans)
    assert out.exists()

    data = json.loads(out.read_text(encoding="utf-8"))
    assert data["metadata"]["span_count"] == 2
    assert [s["name"] for s in data["spans"]] == ["a", "b"]


def test_json_exporter_recovers_from_corrupt_file(tmp_path: Path):
    out = tmp_path / "out.json"
    out.write_text("{not-json", encoding="utf-8")

    exporter = JSONFileExporter(str(out))
    res = exporter.export([_ReadableSpan(trace_id=9, span_id=9, name="x", start_time=1, end_time=2)])

    data = json.loads(out.read_text(encoding="utf-8"))
    assert data["metadata"]["span_count"] == 1
    assert data["spans"][0]["name"] == "x"
