use serde_json::{json, Value as JsonValue};

use super::{
    SessionBundleError, SESSION_BUNDLE_SCHEMA_ID, SESSION_BUNDLE_SCHEMA_VERSION,
    SESSION_BUNDLE_TYPE,
};

pub fn session_bundle_schema() -> JsonValue {
    json!({
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "$id": SESSION_BUNDLE_SCHEMA_ID,
        "title": "Harn Session Bundle v1",
        "type": "object",
        "additionalProperties": true,
        "required": [
            "_type",
            "schema_version",
            "bundle_id",
            "created_at",
            "producer",
            "source",
            "runtime",
            "transcript",
            "tools",
            "permissions",
            "replay",
            "redaction",
            "attachments"
        ],
        "properties": {
            "_type": {"const": SESSION_BUNDLE_TYPE},
            "schema_version": {"type": "integer", "minimum": 1, "maximum": SESSION_BUNDLE_SCHEMA_VERSION},
            "bundle_id": {"type": "string", "minLength": 1},
            "created_at": {"type": "string", "minLength": 1},
            "producer": {
                "type": "object",
                "required": ["name", "version", "schema_id"],
                "additionalProperties": true,
                "properties": {
                    "name": {"type": "string"},
                    "version": {"type": "string"},
                    "schema_id": {"type": "string"}
                }
            },
            "source": {
                "type": "object",
                "required": ["kind", "run_record_id", "workflow_id", "task", "status"],
                "additionalProperties": true,
                "properties": {
                    "kind": {"type": "string"},
                    "run_record_id": {"type": "string"},
                    "workflow_id": {"type": "string"},
                    "workflow_name": {"type": ["string", "null"]},
                    "task": {"type": "string"},
                    "status": {"type": "string"},
                    "started_at": {"type": "string"},
                    "finished_at": {"type": ["string", "null"]},
                    "persisted_path": {"type": ["string", "null"]},
                    "root_run_id": {"type": ["string", "null"]},
                    "parent_run_id": {"type": ["string", "null"]},
                    "child_run_count": {"type": "integer", "minimum": 0}
                }
            },
            "runtime": {
                "type": "object",
                "required": ["harn_version", "provider_models"],
                "additionalProperties": true,
                "properties": {
                    "harn_version": {"type": "string"},
                    "provider_models": {"type": "array", "items": {"type": "string"}},
                    "usage": {"type": ["object", "null"]},
                    "metadata": {"type": "object"}
                }
            },
            "workspace": {"type": ["object", "null"]},
            "transcript": {
                "type": "object",
                "required": ["sections"],
                "additionalProperties": true,
                "properties": {
                    "sections": {
                        "type": "array",
                        "items": {"$ref": "#/$defs/transcript_section"}
                    }
                }
            },
            "tools": {
                "type": "object",
                "required": ["schemas", "calls"],
                "additionalProperties": true,
                "properties": {
                    "schemas": {"type": "array", "items": {"$ref": "#/$defs/json_entry"}},
                    "calls": {"type": "array", "items": {"type": "object"}}
                }
            },
            "permissions": {"type": "array", "items": {"type": "object"}},
            "replay": {
                "type": "object",
                "required": ["event_log_pointers", "transitions", "checkpoints", "trace_spans", "deterministic_events"],
                "additionalProperties": true,
                "properties": {
                    "replay_fixture": {"type": ["object", "null"]},
                    "run_record": {"type": ["object", "null"]},
                    "event_log_pointers": {"type": "array", "items": {"type": "object"}},
                    "transitions": {"type": "array", "items": {"type": "object"}},
                    "checkpoints": {"type": "array", "items": {"type": "object"}},
                    "trace_spans": {"type": "array", "items": {"type": "object"}},
                    "deterministic_events": {"type": "array", "items": {"$ref": "#/$defs/json_entry"}}
                }
            },
            "redaction": {
                "type": "object",
                "required": ["mode", "policy", "placeholder", "entries", "unsafe_secret_markers_rejected"],
                "additionalProperties": true,
                "properties": {
                    "mode": {"enum": ["local", "sanitized", "replay_only"]},
                    "policy": {"type": "string"},
                    "placeholder": {"type": "string"},
                    "entries": {"type": "array", "items": {"type": "object"}},
                    "unsafe_secret_markers_rejected": {"type": "boolean"}
                }
            },
            "attachments": {"type": "array", "items": {"type": "object"}},
            "metadata": {"type": "object"}
        },
        "$defs": {
            "json_entry": {
                "type": "object",
                "required": ["source", "index", "value"],
                "additionalProperties": true,
                "properties": {
                    "source": {"type": "string"},
                    "index": {"type": "integer", "minimum": 0},
                    "value": true
                }
            },
            "transcript_section": {
                "type": "object",
                "required": ["id", "label", "scope", "location", "messages", "events", "assets", "metadata"],
                "additionalProperties": true,
                "properties": {
                    "id": {"type": "string"},
                    "label": {"type": "string"},
                    "scope": {"type": "string"},
                    "location": {"type": "string"},
                    "summary": {"type": ["string", "null"]},
                    "messages": {"type": "array", "items": true},
                    "events": {"type": "array", "items": true},
                    "assets": {"type": "array", "items": true},
                    "metadata": {"type": "object"}
                }
            }
        }
    })
}

pub fn session_bundle_schema_pretty() -> Result<String, SessionBundleError> {
    serde_json::to_string_pretty(&session_bundle_schema())
        .map(|schema| format!("{schema}\n"))
        .map_err(|error| SessionBundleError::Encode(error.to_string()))
}
