"""
CodeContext Client - Lightweight HTTP client for multi-project queries
"""

import sys
import time
import urllib.request
import urllib.error
import json
from typing import List, Optional


class MemoryClient:
    """HTTP client for CodeContext server."""

    def __init__(self, base_url: str = "http://localhost:8765", project: str = "default"):
        self.base_url = base_url.rstrip("/")
        self.project = project

    def _request(self, method: str, path: str, data: Optional[dict] = None) -> dict:
        """Make HTTP request."""
        url = f"{self.base_url}{path}"

        if data:
            body = json.dumps(data).encode('utf-8')
            req = urllib.request.Request(url, data=body, method=method)
            req.add_header('Content-Type', 'application/json')
        else:
            req = urllib.request.Request(url, method=method)

        try:
            with urllib.request.urlopen(req, timeout=30) as response:
                return json.loads(response.read().decode('utf-8'))
        except urllib.error.URLError as e:
            return {"error": f"Connection failed: {e.reason}"}
        except Exception as e:
            return {"error": str(e)}

    def health(self) -> dict:
        """Check server health."""
        return self._request("GET", "/health")

    def projects(self) -> dict:
        """List all projects."""
        return self._request("GET", "/projects")

    def query(self, query: str, top_k: int = 5, project: Optional[str] = None) -> dict:
        """Single query."""
        return self._request("POST", "/query", {
            "query": query,
            "top_k": top_k,
            "project": project or self.project
        })

    def batch_query(self, queries: List[str], top_k: int = 5, project: Optional[str] = None) -> dict:
        """Batch query (multiple queries at once)."""
        return self._request("POST", "/batch-query", {
            "queries": queries,
            "top_k": top_k,
            "project": project or self.project
        })

    def add_memory(
        self,
        obs_type: str,
        title: str,
        fact: str,
        files: List[str] = None,
        project: Optional[str] = None
    ) -> dict:
        """Add a memory to a project."""
        return self._request("POST", "/memory", {
            "type": obs_type,
            "title": title,
            "fact": fact,
            "files": files or [],
            "project": project or self.project
        })

    def stats(self, project: Optional[str] = None) -> dict:
        """Get store statistics."""
        path = f"/stats?project={project}" if project else "/stats"
        return self._request("GET", path)


def print_results(results: List[dict]):
    """Pretty print query results."""
    for i, r in enumerate(results, 1):
        relevance = r.get('relevance_pct', 0)
        label = "GOOD" if relevance >= 50 else "OK" if relevance >= 30 else "LOW"
        print(f"\n{i}. [{r['type']}] {r['title']}")
        print(f"   Match: {relevance:.0f}% ({label})")
        print(f"   {r['fact'][:100]}...")


def print_usage():
    """Print CLI usage."""
    print("CodeContext Client - Multi-Project")
    print()
    print("Usage:")
    print("  codecontext health")
    print("  codecontext projects")
    print("  codecontext query 'search term'")
    print("  codecontext batch 'term1' 'term2' 'term3'")
    print("  codecontext stats")
    print()
    print("Examples:")
    print("  codecontext query 'datetime bug'")
    print("  codecontext batch 'auth' 'database' 'api'")
    print("  codecontext stats --json")


# CLI usage
if __name__ == "__main__":
    client = MemoryClient()

    if len(sys.argv) < 2:
        print_usage()
        sys.exit(0)

    cmd = sys.argv[1]

    if cmd == "health":
        result = client.health()
        if "error" in result:
            print(f"Error: {result['error']}")
            print("Is the server running? Start with: codecontext server")
        else:
            print(f"Status: {result['status']}")
            print(f"Model: {result['model']}")
            print(f"Device: {result['device']}")
            print(f"Base path: {result['base_path']}")
            print(f"Projects: {result['project_count']}")
            if result['gpu']['available']:
                print(f"GPU: {result['gpu']['name']}")

    elif cmd == "projects":
        result = client.projects()
        if "error" in result:
            print(f"Error: {result['error']}")
        else:
            print(f"Found {result['count']} projects:")
            for p in result['projects']:
                print(f"  - {p['name']}: {p['memory_count']} memories")

    elif cmd == "query" and len(sys.argv) > 3:
        project = sys.argv[2]
        query = " ".join(sys.argv[3:])
        print(f"Searching [{project}]: {query}")
        start = time.time()
        result = client.query(query, project=project)
        elapsed = (time.time() - start) * 1000

        if "error" in result:
            print(f"Error: {result['error']}")
        else:
            print(f"Found {result['count']} results in {elapsed:.0f}ms")
            print_results(result['results'])

    elif cmd == "batch" and len(sys.argv) > 3:
        project = sys.argv[2]
        queries = sys.argv[3:]
        print(f"Batch query [{project}]: {len(queries)} queries")
        start = time.time()
        result = client.batch_query(queries, project=project)
        elapsed = (time.time() - start) * 1000

        if "error" in result:
            print(f"Error: {result['error']}")
        else:
            print(f"Total time: {result['total_time_ms']:.0f}ms")
            print(f"Avg per query: {result['avg_time_ms']:.0f}ms")
            for batch in result['batch_results']:
                print(f"\n--- Query: {batch['query']} ---")
                print_results(batch['results'][:3])

    elif cmd == "stats":
        project = sys.argv[2] if len(sys.argv) > 2 else None
        result = client.stats(project)
        if "error" in result:
            print(f"Error: {result['error']}")
        elif project:
            print(f"Project: {result['project']}")
            print(f"Memories: {result['memory_count']}")
            print(f"Device: {result['device']}")
            print(f"DB Path: {result['db_path']}")
        else:
            print(f"Base path: {result['base_path']}")
            print(f"Model: {result['model']}")
            print(f"Device: {result['device']}")
            print(f"Projects: {result['project_count']}")
            print(f"Total memories: {result['total_memories']}")
            if result['projects']:
                print(f"Project list: {', '.join(result['projects'])}")

    else:
        print_usage()
