#!/usr/bin/env python3
"""
test_ollama_provider.py — Smoke test for the Ollama parsing provider.

Run from the nterm project root:
    python test_ollama_provider.py

Tests:
  1. Health check (can we reach Ollama?)
  2. Parse sample 'show ip bgp summary' output
  3. Parse sample 'show interfaces' output
  4. Score validation
"""

import json
import sys
import time
import logging

# ── Logging ─────────────────────────────────────────────────
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(name)s] %(levelname)s: %(message)s",
    datefmt="%H:%M:%S",
)
log = logging.getLogger("test_ollama")

# ── Import provider directly ────────────────────────────────
try:
    from parsing.providers import OllamaProvider
    from parsing.config import load_parse_config
except ImportError:
    # If running from project root without package install
    sys.path.insert(0, ".")
    from parsing.providers import OllamaProvider
    from parsing.config import load_parse_config


# ── Sample CLI Outputs ──────────────────────────────────────

BGP_SUMMARY = """\
BGP router identifier 10.0.0.1, local AS number 65001
BGP table version is 42, main routing table version 42
6 network entries using 864 bytes of memory
6 path entries using 480 bytes of memory

Neighbor        V  AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
10.0.0.2        4 65002    1204    1198       42    0    0 01:02:33        3
10.0.0.3        4 65003     987     992       42    0    0 00:45:12        2
10.0.0.4        4 65004       0       0        0    0    0 never    Active
192.168.1.1     4 65100    5432    5401       42    0    0 3d04h           1
"""

SHOW_INTERFACES = """\
GigabitEthernet0/0 is up, line protocol is up
  Hardware is iGbE, address is 0050.5600.0001 (bia 0050.5600.0001)
  Internet address is 10.0.0.1/30
  MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec,
     reliability 255/255, txload 1/255, rxload 1/255
  5 minute input rate 1234000 bits/sec, 892 packets/sec
  5 minute output rate 987000 bits/sec, 654 packets/sec
GigabitEthernet0/1 is up, line protocol is up
  Hardware is iGbE, address is 0050.5600.0002 (bia 0050.5600.0002)
  Internet address is 10.0.1.1/30
  MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec,
     reliability 255/255, txload 1/255, rxload 1/255
  5 minute input rate 567000 bits/sec, 423 packets/sec
  5 minute output rate 321000 bits/sec, 210 packets/sec
GigabitEthernet0/2 is administratively down, line protocol is down
  Hardware is iGbE, address is 0050.5600.0003 (bia 0050.5600.0003)
  Internet address is 172.16.0.1/24
  MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec,
     reliability 255/255, txload 0/255, rxload 0/255
"""


# ── Helpers ─────────────────────────────────────────────────

def divider(title: str):
    print(f"\n{'─' * 60}")
    print(f"  {title}")
    print(f"{'─' * 60}")


def dump_result(result):
    """Pretty-print a ProviderResult."""
    print(f"  provider:      {result.provider}")
    print(f"  score:         {result.score}/100")
    print(f"  parse_time_ms: {result.parse_time_ms}")
    print(f"  fields:        {result.fields}")
    print(f"  record_count:  {len(result.records)}")
    if result.error:
        print(f"  error:         {result.error}")
    if result.records:
        print(f"  records:")
        for i, rec in enumerate(result.records[:5]):  # cap at 5
            print(f"    [{i}] {json.dumps(rec, indent=None)}")
        if len(result.records) > 5:
            print(f"    ... +{len(result.records) - 5} more")


# ── Main ────────────────────────────────────────────────────

def main():
    # Load config to get Ollama settings from parsers_config.yaml
    cfg = load_parse_config()
    ocfg = cfg.ollama

    print(f"Ollama config: {ocfg.base_url}  model={ocfg.model}  timeout={ocfg.timeout_s}s")

    provider = OllamaProvider(
        base_url=ocfg.base_url,
        model=ocfg.model,
        timeout_s=ocfg.timeout_s,
        max_output_chars=ocfg.max_output_chars,
        health_check_interval_s=0,  # force check every time
    )

    # ── Test 1: Health check ────────────────────────────────
    divider("Test 1: Health Check")
    available = provider.check_availability()
    print(f"  available: {available}")
    if not available:
        print(f"\n  Ollama not reachable at {ocfg.base_url}")
        print(f"  Make sure 'ollama serve' is running and the model is pulled:")
        print(f"    ollama pull {ocfg.model}")
        sys.exit(1)
    print("  ✓ Ollama is reachable")

    # ── Test 2: BGP Summary ─────────────────────────────────
    divider("Test 2: Parse 'show ip bgp summary'")
    filter_str = "cisco_ios_show_ip_bgp_summary"
    t0 = time.monotonic()
    result = provider.parse(BGP_SUMMARY, filter_str)
    wall = int((time.monotonic() - t0) * 1000)
    dump_result(result)
    print(f"  wall_time_ms:  {wall}")

    if result.score > 0 and len(result.records) >= 3:
        print("  ✓ BGP parse looks good")
    else:
        print("  ✗ BGP parse returned unexpected results")

    # ── Test 3: Show Interfaces ─────────────────────────────
    divider("Test 3: Parse 'show interfaces'")
    filter_str = "cisco_ios_show_interfaces"
    t0 = time.monotonic()
    result = provider.parse(SHOW_INTERFACES, filter_str)
    wall = int((time.monotonic() - t0) * 1000)
    dump_result(result)
    print(f"  wall_time_ms:  {wall}")

    if result.score > 0 and len(result.records) >= 2:
        print("  ✓ Interface parse looks good")
    else:
        print("  ✗ Interface parse returned unexpected results")

    # ── Test 4: Oversized output rejection ──────────────────
    divider("Test 4: Oversized output rejection")
    big_output = "x" * (ocfg.max_output_chars + 1)
    result = provider.parse(big_output, "test_big")
    print(f"  error: {result.error}")
    if result.error and "too large" in result.error:
        print("  ✓ Correctly rejected oversized output")
    else:
        print("  ✗ Should have rejected oversized output")

    # ── Test 5: Score breakdown (manual check) ──────────────
    divider("Test 5: Score factor sanity")
    # Build a known-good record set and verify scoring
    fake_records = [
        {"neighbor": "10.0.0.1", "as_number": "65001", "state": "Established", "prefixes": "5"},
        {"neighbor": "10.0.0.2", "as_number": "65002", "state": "Established", "prefixes": "3"},
        {"neighbor": "10.0.0.3", "as_number": "65003", "state": "Active", "prefixes": "0"},
    ]
    score = provider._score_records(fake_records)
    print(f"  3 records × 4 fields, fully populated → score: {score}")
    if 40 <= score <= 75:
        print("  ✓ Score in expected range")
    else:
        print(f"  ✗ Score {score} outside expected range (40–75)")

    divider("Done")
    print()


if __name__ == "__main__":
    main()