"""
POY Verify Python SDK
Human verification API client

Usage:
    from poyverify import POYVerify

    poy = POYVerify(api_key="poy_live_xxxxxxxxxxxx")
    result = poy.verify("PoY #A3F9C2E")
    print(result.verified)    # True
    print(result.trust_score) # 98.2

Documentation: https://poyverify.com/docs
"""

import hashlib
import json
import urllib.request
import urllib.error
import urllib.parse
from dataclasses import dataclass
from typing import Optional, Dict, Any, List


@dataclass
class VerifyResult:
    verified: bool
    human_status: str
    trust_score: float
    confidence: float
    verification_count: int
    last_verified_at: Optional[str]
    poy_id: str
    raw: Dict[str, Any]


@dataclass
class Profile:
    poy_id: str
    is_human: bool
    trust_score: float
    verification_count: int
    total_stamps: int
    status: str
    badges: List[str]
    verified_since: Optional[str]
    raw: Dict[str, Any]


@dataclass
class Stamp:
    stamp_id: str
    content_hash: str
    signature: str
    author: str
    created_at: str
    human_verified: bool
    raw: Dict[str, Any]


@dataclass
class StampVerification:
    authentic: bool
    stamp_id: str
    author: str
    author_trust_score: float
    content_hash: str
    signature_valid: bool
    chain_of_custody: str
    human_verified: bool
    created_at: str
    raw: Dict[str, Any]


class POYVerifyError(Exception):
    def __init__(self, message: str, status: int = 0, response: dict = None):
        super().__init__(message)
        self.status = status
        self.response = response or {}


class POYVerify:
    """POY Verify API client for human verification."""

    VERSION = "0.1.0"

    def __init__(self, api_key: str, base_url: str = "https://poyverify.com/api/poy", timeout: int = 10):
        if not api_key or not isinstance(api_key, str):
            raise ValueError("POY Verify: API key is required. Get one at poyverify.com")
        if not api_key.startswith("poy_live_") and not api_key.startswith("poy_test_"):
            raise ValueError("POY Verify: Invalid API key format. Keys start with poy_live_ or poy_test_")

        self.api_key = api_key
        self.base_url = base_url
        self.timeout = timeout

    def _request(self, method: str, endpoint: str, body: dict = None) -> dict:
        url = f"{self.base_url}{endpoint}"
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json",
            "X-SDK-Version": self.VERSION,
        }

        data = json.dumps(body).encode("utf-8") if body else None
        req = urllib.request.Request(url, data=data, headers=headers, method=method)

        try:
            with urllib.request.urlopen(req, timeout=self.timeout) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except urllib.error.HTTPError as e:
            error_body = {}
            try:
                error_body = json.loads(e.read().decode("utf-8"))
            except Exception:
                pass
            raise POYVerifyError(
                error_body.get("error", f"API error: {e.code}"),
                status=e.code,
                response=error_body,
            )
        except urllib.error.URLError as e:
            raise POYVerifyError(f"Connection error: {e.reason}")

    def verify(self, user_id: str, biometric_hash: str = None) -> VerifyResult:
        """Verify if a user is a real human."""
        if not user_id:
            raise ValueError("user_id is required")

        body = {"poy_id": user_id}
        if biometric_hash:
            body["biometric_hash"] = biometric_hash

        data = self._request("POST", "/verify", body)

        return VerifyResult(
            verified=data.get("verified", False),
            human_status=data.get("human_status", "unconfirmed"),
            trust_score=data.get("trust_score", 0),
            confidence=data.get("confidence", 0),
            verification_count=data.get("verification_count", 0),
            last_verified_at=data.get("last_verified_at"),
            poy_id=data.get("poy_id", user_id),
            raw=data,
        )

    def is_human(self, user_id: str) -> bool:
        """Quick boolean check - is this user a verified human?"""
        if not user_id:
            raise ValueError("user_id is required")

        data = self._request("GET", f"/check?poy_id={urllib.parse.quote(user_id)}")
        return data.get("isHuman", False)

    def get_profile(self, user_id: str) -> Profile:
        """Get a user's public profile."""
        if not user_id:
            raise ValueError("user_id is required")

        data = self._request("GET", f"/profile?id={urllib.parse.quote(user_id)}")

        return Profile(
            poy_id=data.get("poy_id", ""),
            is_human=data.get("isHuman", False),
            trust_score=data.get("trust_score", 0),
            verification_count=data.get("verification_count", 0),
            total_stamps=data.get("total_stamps", 0),
            status=data.get("status", "unknown"),
            badges=data.get("badges", []),
            verified_since=data.get("created_at"),
            raw=data,
        )

    def stamp(self, content_hash: str, author_id: str, content_type: str = "text", metadata: dict = None) -> Stamp:
        """Stamp content as human-made."""
        if not content_hash:
            raise ValueError("content_hash is required")
        if not author_id:
            raise ValueError("author_id is required")

        data = self._request("POST", "/stamp/create", {
            "poy_id": author_id,
            "content_hash": content_hash,
            "content_type": content_type,
            "metadata": metadata or {},
        })

        return Stamp(
            stamp_id=data.get("stamp_id", ""),
            content_hash=data.get("content_hash", ""),
            signature=data.get("signature", ""),
            author=data.get("author", ""),
            created_at=data.get("created_at", ""),
            human_verified=True,
            raw=data,
        )

    def check_stamp(self, stamp_id: str = None, content_hash: str = None) -> StampVerification:
        """Verify a content stamp is authentic."""
        if not stamp_id and not content_hash:
            raise ValueError("stamp_id or content_hash is required")

        body = {}
        if stamp_id:
            body["stamp_id"] = stamp_id
        if content_hash:
            body["content_hash"] = content_hash

        data = self._request("POST", "/stamp/verify", body)

        return StampVerification(
            authentic=data.get("authentic", False),
            stamp_id=data.get("stamp_id", ""),
            author=data.get("author", ""),
            author_trust_score=data.get("author_trust_score", 0),
            content_hash=data.get("content_hash", ""),
            signature_valid=data.get("signature_valid", False),
            chain_of_custody=data.get("chain_of_custody", "unknown"),
            human_verified=data.get("authentic", False),
            created_at=data.get("created_at", ""),
            raw=data,
        )

    def trust_score(self, user_id: str) -> float:
        """Get a user's trust score (0-100)."""
        profile = self.get_profile(user_id)
        return profile.trust_score

    @staticmethod
    def hash(content: str) -> str:
        """Generate SHA-256 hash of content."""
        if isinstance(content, str):
            content = content.encode("utf-8")
        return hashlib.sha256(content).hexdigest()

    def ping(self) -> bool:
        """Check if the SDK can reach the API."""
        try:
            self._request("GET", "/health")
            return True
        except Exception:
            return False
