use serde_json::json;

use super::types::*;

// ---------------------------------------------------------------------------
// /ai.txt — plain-text API summary for LLM context windows
// ---------------------------------------------------------------------------

pub fn generate_ai_txt(c: &ContentConfig) -> String {
    format!(
        r#"# {name} v{version}

{description}

## What this API does
Provides sanctions screening data for blockchain applications. Ingests sanctioned
crypto addresses from the U.S. Treasury OFAC SDN list and known ransomware payment
addresses, then serves them via a simple HTTP API.

## Endpoints

GET {lists} — Public. Returns all sanctioned wallet addresses and country codes.
GET {check} — Requires X-API-Key. Check a single address against the sanctions DB.

## Data sources
- OFAC SDN Advanced XML (official U.S. Treasury, ~772 crypto addresses, 18 currency types)
- Ransomware tracker (ransomwhe.re, known ransomware payment addresses)

## More info
- Endpoint details: {llms}
- Full schemas: {llms_full}
- Agent guide: {agent}
- OpenAPI spec: {openapi}
"#,
        name = c.name,
        version = c.version,
        description = c.description,
        lists = c.path("/v1/lists"),
        check = c.path("/v1/check/{currency}?address={address}"),
        llms = c.path("/llms.txt"),
        llms_full = c.path("/llms-full.txt"),
        agent = c.path("/agent.md"),
        openapi = c.path("/openapi.json"),
    )
}

// ---------------------------------------------------------------------------
// /llms.txt — concise endpoint reference (follows llmstxt.org spec)
// ---------------------------------------------------------------------------

pub fn generate_llms_txt(c: &ContentConfig) -> String {
    format!(
        r#"# {name}

> {description}

## Endpoints

GET {lists}
  Auth: None
  Returns all sanctioned addresses and country codes as flat arrays.

GET {check}
  Auth: X-API-Key header
  Check if a specific address is on a sanctions list.

## Skills
- [{sanctions_skill}]({sanctions_skill}): Sanctions screening workflow
"#,
        name = c.name,
        description = c.description,
        lists = c.path("/v1/lists"),
        check = c.path("/v1/check/{{currency}}?address={{address}}"),
        sanctions_skill = c.path("/skills/sanctions.md"),
    )
}

// ---------------------------------------------------------------------------
// /llms-full.txt — expanded with request/response schemas
// ---------------------------------------------------------------------------

pub fn generate_llms_full_txt(c: &ContentConfig) -> String {
    format!(
        r#"# {name} v{version} — Full API Reference

## GET {lists}

Public endpoint. No authentication required.

Returns all sanctioned blockchain addresses and ISO country codes.

Response 200:
```json
{{
  "addresses": ["addr1", "addr2", "..."],
  "countries": ["KP", "IR", "SY", "CU"]
}}
```

Fields:
- addresses: string[] — flat list of sanctioned wallet addresses across all blockchains.
  Lookups should be exact string match (addresses are case-sensitive).
- countries: string[] — ISO 3166-1 alpha-2 country codes of sanctioned jurisdictions,
  deduplicated and sorted. Uppercase.

Both arrays may be empty ([]).

---

## GET {check}

Requires `X-API-Key` header.

Check a single address against the sanctions database for a given currency.

Path parameters:
- currency (string, required) — blockchain identifier (e.g., BTC, ETH, SOL, USDT).
  Normalized automatically (XBT→BTC, ethereum→ETH, etc.).

Query parameters:
- address (string, required) — the wallet address to check.

Response 200 (found):
```json
{{
  "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
  "onList": true,
  "listName": "OFAC",
  "confidence": 100
}}
```

Response 200 (not found):
```json
{{
  "address": "someCleanAddress123",
  "onList": false,
  "confidence": 0
}}
```

Response 401:
```json
{{"error": "Invalid API key"}}
```
"#,
        name = c.name,
        version = c.version,
        lists = c.path("/v1/lists"),
        check = c.path("/v1/check/{currency}?address={address}"),
    )
}

// ---------------------------------------------------------------------------
// /llms-admin.txt — admin/authenticated endpoints
// ---------------------------------------------------------------------------

pub fn generate_llms_admin_txt(c: &ContentConfig) -> String {
    format!(
        r#"# {name} — Authenticated Endpoints

## GET {check}

Requires: X-API-Key header

Check a single address against the sanctions database.
See /llms-full.txt for full request/response schemas.

## Authentication

All authenticated endpoints require an `X-API-Key` header.
API keys are managed in the `api_keys` database table.
Invalid or inactive keys return 401.
"#,
        name = c.name,
        check = c.path("/v1/check/{currency}?address={address}"),
    )
}

// ---------------------------------------------------------------------------
// /agent.md — structured agent integration guide
// ---------------------------------------------------------------------------

pub fn generate_agent_md(c: &ContentConfig) -> String {
    format!(
        r#"---
title: Agent Integration Guide
version: "{version}"
audience: AI agents, automated systems
---

# {name} — Agent Integration Guide

## Overview

{description}. Use this API to screen blockchain addresses and countries
against sanctions lists before processing transactions.

## Typical Agent Workflow

1. **Fetch the sanctions list** — `GET {lists}` (no auth needed)
2. **Cache locally** — store addresses in a HashSet for O(1) lookups
3. **Screen transactions** — check wallet addresses against your cached set
4. **Refresh periodically** — re-fetch every hour (data updates hourly)

## Quick Start

### Fetch the full sanctions list

```bash
curl {lists}
```

Response:
```json
{{
  "addresses": ["addr1", "addr2"],
  "countries": ["KP", "IR", "SY", "CU"]
}}
```

### Check a single address (requires API key)

```bash
curl -H "X-API-Key: your-key" "{check}"
```

Response:
```json
{{
  "address": "addr1",
  "onList": true,
  "listName": "OFAC",
  "confidence": 100
}}
```

## Integration Examples

### Python

```python
import requests

# Fetch full list (no auth)
resp = requests.get("{lists}")
data = resp.json()

sanctioned_addresses = set(data["addresses"])
sanctioned_countries = set(data["countries"])

# Screen a wallet
wallet = "FW3g7yRSFCVPJsiBaKFbuiCfGHPPCKqBjP2rMXkmCjBr"
if wallet in sanctioned_addresses:
    print("BLOCKED: sanctioned address")
```

### Rust

```rust
use std::collections::HashSet;

#[derive(serde::Deserialize)]
struct SanctionsList {{
    addresses: Vec<String>,
    countries: Vec<String>,
}}

let resp: SanctionsList = reqwest::get("{lists}")
    .await?.json().await?;

let blocked: HashSet<String> = resp.addresses.into_iter().collect();

if blocked.contains(&wallet_address) {{
    // reject transaction
}}
```

### JavaScript

```javascript
const resp = await fetch("{lists}");
const {{ addresses, countries }} = await resp.json();
const blocked = new Set(addresses);

if (blocked.has(walletAddress)) {{
  throw new Error("Sanctioned address");
}}
```

## Error Handling

| Status | Meaning | Action |
|--------|---------|--------|
| 200 | Success | Process response |
| 401 | Invalid/inactive API key | Check your X-API-Key header |
| 500 | Server error | Retry with backoff, fall back to cached data |

## Data Sources

- **OFAC SDN** — U.S. Treasury Office of Foreign Assets Control. Official sanctions list.
- **Ransomware tracker** — Community-maintained list of known ransomware payment addresses.

## Refresh Recommendations

- Fetch `/v1/lists` once per hour (data refreshes hourly from sources)
- Cache the response locally for fast lookups
- On fetch failure, keep using the previous cached data
"#,
        name = c.name,
        version = c.version,
        description = c.description,
        lists = c.path("/v1/lists"),
        check = c.path("/v1/check/SOL?address=ExampleAddress123"),
    )
}

// ---------------------------------------------------------------------------
// /skill.md — skill manifest with YAML frontmatter
// ---------------------------------------------------------------------------

pub fn generate_skill_md(c: &ContentConfig) -> String {
    format!(
        r#"---
name: {name}
version: "{version}"
description: {description}
category: compliance
apiBase: "{base_path}"
capabilities:
  sanctionsList: true
  addressCheck: true
  countryCodes: true
authentication:
  methods: [api-key]
  header: "X-API-Key: <key>"
  note: "Only GET /v1/check requires auth. GET /v1/lists is public."
skills:
  - id: sanctions
    path: {sanctions_skill}
    requiresAuth: false
---

# {name} Skills

## Available Skills

| Skill | Description | Auth Required |
|-------|-------------|---------------|
| [Sanctions Screening]({sanctions_skill}) | Fetch and use sanctions lists for compliance | No (list) / Yes (check) |
"#,
        name = c.name,
        version = c.version,
        description = c.description,
        base_path = c.base_path,
        sanctions_skill = c.path("/skills/sanctions.md"),
    )
}

// ---------------------------------------------------------------------------
// /skills/sanctions.md — individual skill file
// ---------------------------------------------------------------------------

pub fn generate_skill_sanctions_md(c: &ContentConfig) -> String {
    format!(
        r#"---
skill: sanctions
name: Sanctions Screening
version: "{version}"
description: Fetch sanctioned addresses and country codes for compliance screening
apiBase: "{base_path}"
requiresAuth: false
---

# Sanctions Screening Skill

## Purpose

Screen blockchain wallet addresses and user countries against sanctions lists
before processing transactions. Prevents interaction with OFAC-sanctioned entities
and known ransomware operators.

## Workflow

### Step 1: Fetch the sanctions list

```
GET {lists}
```

No authentication required. Response:

```json
{{
  "addresses": ["addr1", "addr2", "..."],
  "countries": ["KP", "IR", "SY", "CU", "..."]
}}
```

### Step 2: Cache locally

Store `addresses` in a HashSet<String> for O(1) lookups.
Store `countries` in a HashSet<String> (already uppercase).

### Step 3: Screen transactions

For each incoming transaction:
1. Check the sender's wallet address against the addresses set (exact match, case-sensitive)
2. If you have country data for the user, check against the countries set

### Step 4: Refresh periodically

Re-fetch `GET {lists}` every hour. On failure, keep using cached data.

## Single-address check (alternative)

If you prefer server-side checking instead of local caching:

```
GET {check}
X-API-Key: your-key
```

Response when found:
```json
{{
  "address": "addr1",
  "onList": true,
  "listName": "OFAC",
  "confidence": 100
}}
```

Response when clean:
```json
{{
  "address": "addr1",
  "onList": false,
  "confidence": 0
}}
```

## Supported currencies

BTC, ETH, SOL, USDT, USDC, XRP, LTC, TRX, XMR, DASH, ZEC, BCH, XVG, ETC, BTG,
BSV, ARB, BSC (18 total from OFAC SDN list).

## Country codes

ISO 3166-1 alpha-2 codes for comprehensively sanctioned jurisdictions.
Common codes: CU (Cuba), IR (Iran), KP (North Korea), SY (Syria), RU (Russia),
BY (Belarus), VE (Venezuela), NI (Nicaragua), MM (Myanmar).
"#,
        version = c.version,
        base_path = c.base_path,
        lists = c.path("/v1/lists"),
        check = c.path("/v1/check/{{currency}}?address={{address}}"),
    )
}

// ---------------------------------------------------------------------------
// /heartbeat.md
// ---------------------------------------------------------------------------

pub fn generate_heartbeat_md(c: &ContentConfig) -> String {
    format!(
        r#"# {name} Heartbeat

**Status:** operational
**Version:** {version}

## Capabilities
- Sanctions list retrieval (GET {lists})
- Single-address check (GET {check})

## Health
Service is running and accepting requests.
"#,
        name = c.name,
        version = c.version,
        lists = c.path("/v1/lists"),
        check = c.path("/v1/check/{currency}?address={address}"),
    )
}

// ---------------------------------------------------------------------------
// Structured data generators
// ---------------------------------------------------------------------------

pub fn build_discovery_index(c: &ContentConfig) -> AiDiscoveryIndex {
    AiDiscoveryIndex {
        version: "1.0.0".into(),
        name: c.name.clone(),
        description: c.description.clone(),
        endpoints: DiscoveryEndpoints {
            llms_txt: c.path("/llms.txt"),
            llms_full_txt: c.path("/llms-full.txt"),
            llms_admin_txt: c.path("/llms-admin.txt"),
            skill_index_markdown: c.path("/skill.md"),
            skill_index_json: c.path("/skill.json"),
            agent_guide: c.path("/agent.md"),
            openapi: c.path("/openapi.json"),
            a2a_agent_card: c.path("/.well-known/agent.json"),
            ai_plugin: c.path("/.well-known/ai-plugin.json"),
            mcp: c.path("/.well-known/mcp"),
            health: c.path("/heartbeat.json"),
            skills_bundle: c.path("/.well-known/skills.zip"),
        },
        skills: vec![build_sanctions_skill_ref(c)],
    }
}

pub fn build_sanctions_skill_ref(c: &ContentConfig) -> SkillReference {
    SkillReference {
        id: "sanctions".into(),
        name: "Sanctions Screening".into(),
        path: c.path("/skills/sanctions.md"),
        description: "Fetch and use sanctions lists for compliance screening".into(),
        requires_auth: false,
    }
}

pub fn build_skill_metadata(c: &ContentConfig) -> SkillMetadata {
    SkillMetadata {
        name: c.name.clone(),
        version: c.version.clone(),
        description: c.description.clone(),
        category: "compliance".into(),
        api_base: c.base_path.clone(),
        capabilities: SkillCapabilities {
            sanctions_list: true,
            address_check: true,
            country_codes: true,
        },
        authentication: SkillAuth {
            methods: vec!["api-key".into()],
            header: "X-API-Key: <key>".into(),
            note: "Only GET /v1/check requires auth. GET /v1/lists is public.".into(),
        },
        skills: vec![build_sanctions_skill_ref(c)],
    }
}

pub fn build_ai_plugin_manifest(c: &ContentConfig) -> AiPluginManifest {
    AiPluginManifest {
        schema_version: "v1".into(),
        name_for_human: "Cedros Sunscreen".into(),
        name_for_model: "cedros_sunscreen".into(),
        description_for_human: c.description.clone(),
        description_for_model: "Sanctions screening API. Use GET /v1/lists for the full \
            sanctions list (addresses + country codes). Use GET /v1/check/{currency}?address=X \
            with X-API-Key header to check a single address."
            .into(),
        auth: AiPluginAuth {
            auth_type: "none".into(),
        },
        api: AiPluginApi {
            api_type: "openapi".into(),
            url: c.path("/openapi.json"),
        },
    }
}

pub fn build_agent_card(c: &ContentConfig) -> AgentCard {
    AgentCard {
        name: c.name.clone(),
        description: c.description.clone(),
        url: c.base_path.clone(),
        version: c.version.clone(),
        capabilities: AgentCapabilities {
            sanctions_screening: true,
            country_screening: true,
            bulk_list_download: true,
        },
        skills: vec![AgentSkill {
            id: "sanctions".into(),
            name: "Sanctions Screening".into(),
            description: "Fetch and use sanctions lists for compliance screening".into(),
            documentation_url: c.path("/skills/sanctions.md"),
        }],
    }
}

pub fn build_mcp_discovery(c: &ContentConfig) -> McpDiscovery {
    McpDiscovery {
        name: c.name.clone(),
        version: c.version.clone(),
        description: c.description.clone(),
        tools: vec![
            McpTool {
                name: "get_sanctions_list".into(),
                description: "Fetch all sanctioned addresses and country codes".into(),
                input_schema: json!({"type": "object", "properties": {}}),
            },
            McpTool {
                name: "check_address".into(),
                description: "Check if a specific address is sanctioned".into(),
                input_schema: json!({
                    "type": "object",
                    "properties": {
                        "currency": {"type": "string", "description": "Blockchain (BTC, ETH, SOL, etc.)"},
                        "address": {"type": "string", "description": "Wallet address to check"}
                    },
                    "required": ["currency", "address"]
                }),
            },
        ],
    }
}

pub fn build_heartbeat(c: &ContentConfig) -> HeartbeatResponse {
    HeartbeatResponse {
        status: "operational".into(),
        name: c.name.clone(),
        version: c.version.clone(),
        capabilities: vec![
            "sanctions-list".into(),
            "address-check".into(),
            "country-codes".into(),
        ],
        endpoints: vec![
            c.path("/v1/lists"),
            c.path("/v1/check/{currency}"),
        ],
    }
}

pub fn build_openapi_spec(c: &ContentConfig) -> serde_json::Value {
    json!({
        "openapi": "3.0.3",
        "info": {
            "title": c.name,
            "version": c.version,
            "description": c.description,
        },
        "paths": {
            c.path("/v1/lists"): {
                "get": {
                    "operationId": "getSanctionsList",
                    "summary": "Get all sanctioned addresses and country codes",
                    "tags": ["sanctions"],
                    "responses": {
                        "200": {
                            "description": "Sanctions list",
                            "content": {
                                "application/json": {
                                    "schema": { "$ref": "#/components/schemas/SanctionsListResponse" }
                                }
                            }
                        }
                    }
                }
            },
            c.path("/v1/check/{currency}"): {
                "get": {
                    "operationId": "checkAddress",
                    "summary": "Check a single address against the sanctions database",
                    "tags": ["sanctions"],
                    "security": [{ "apiKey": [] }],
                    "parameters": [
                        {
                            "name": "currency",
                            "in": "path",
                            "required": true,
                            "schema": { "type": "string" },
                            "description": "Blockchain identifier (BTC, ETH, SOL, etc.)"
                        },
                        {
                            "name": "address",
                            "in": "query",
                            "required": true,
                            "schema": { "type": "string" },
                            "description": "Wallet address to check"
                        }
                    ],
                    "responses": {
                        "200": {
                            "description": "Address check result",
                            "content": {
                                "application/json": {
                                    "schema": { "$ref": "#/components/schemas/AddressCheckResult" }
                                }
                            }
                        },
                        "401": {
                            "description": "Invalid or missing API key"
                        }
                    }
                }
            }
        },
        "components": {
            "securitySchemes": {
                "apiKey": {
                    "type": "apiKey",
                    "in": "header",
                    "name": "X-API-Key"
                }
            },
            "schemas": {
                "SanctionsListResponse": {
                    "type": "object",
                    "properties": {
                        "addresses": {
                            "type": "array",
                            "items": { "type": "string" },
                            "description": "Sanctioned wallet addresses (all blockchains, exact match)"
                        },
                        "countries": {
                            "type": "array",
                            "items": { "type": "string" },
                            "description": "ISO 3166-1 alpha-2 country codes of sanctioned jurisdictions"
                        }
                    },
                    "required": ["addresses", "countries"]
                },
                "AddressCheckResult": {
                    "type": "object",
                    "properties": {
                        "address": { "type": "string" },
                        "onList": { "type": "boolean" },
                        "listName": { "type": "string", "nullable": true },
                        "confidence": { "type": "integer", "minimum": 0, "maximum": 100 }
                    },
                    "required": ["address", "onList", "confidence"]
                }
            }
        }
    })
}
