import os
import json
import time
import socket
from socketserver import UnixStreamServer
from http.server import BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs

import secure_swarm_protocol

SOCKET_PATH = "/tmp/axiom_zero_api.sock"
START_TIME = time.time()

import sys
sys.path.insert(0, os.path.dirname(__file__))
from customer_db import _db as customer_db_instance

class UnixHTTPServer(UnixStreamServer):
    def get_request(self):
        request, client_address = super().get_request()
        return (request, ["local", 0])

class APIHandler(BaseHTTPRequestHandler):
    def _send_response(self, status_code, payload):
        self.send_response(status_code)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps(payload).encode('utf-8'))

    def _send_error(self, status_code, message):
        self._send_response(status_code, {"error": message})

    def do_GET(self):
        parsed_path = urlparse(self.path)
        path = parsed_path.path
        query = parse_qs(parsed_path.query)

        if path == "/v1/health":
            uptime = time.time() - START_TIME
            count = len(customer_db_instance.get_all_customers())
            self._send_response(200, {
                "status": "ok",
                "daemon_uptime": uptime,
                "db_customers": count
            })
            
        elif path == "/v1/customers":
            self._send_response(200, customer_db_instance.get_all_customers())
            
        elif path == "/v1/events":
            limit = 50
            if "limit" in query:
                try:
                    limit = int(query["limit"][0])
                except ValueError:
                    self._send_error(400, "Invalid limit parameter")
                    return
            self._send_response(200, customer_db_instance.get_recent_events(limit))
            
        elif path == "/v1/stats":
            # For now, we can compute stats from events or return mock if not implemented in db.
            # Assuming recent events cover stats for simplicity, but the instruction doesn't specify how to fix stats precisely.
            # Let's compute them from recent events or skip stats since customer_db._db doesn't have a stats property.
            # Actually, I will just return 0 for now or compute from get_recent_events.
            events = customer_db_instance.get_recent_events(1000)
            t_blocked = sum(1 for e in events if e.get("outcome") == "blocked")
            t_allowed = len(events) - t_blocked
            t_count = len(events)
            l_sum = sum(e.get("latency_ms", 0.0) for e in events)
            block_rate = (t_blocked / t_count) if t_count > 0 else 0.0
            avg_latency = (l_sum / t_count) if t_count > 0 else 0.0
            
            self._send_response(200, {
                "total_blocked": t_blocked,
                "total_allowed": t_allowed,
                "block_rate": block_rate,
                "avg_latency_ms": avg_latency
            })
            
        else:
            self._send_error(404, "Not Found")

    def do_POST(self):
        parsed_path = urlparse(self.path)
        path = parsed_path.path

        try:
            content_length = int(self.headers.get('Content-Length', 0))
        except ValueError:
            self._send_error(400, "Invalid Content-Length")
            return
            
        if content_length < 0:
            self._send_error(400, "Negative Content-Length")
            return
            
        if content_length > 1 * 1024 * 1024:
            self._send_error(413, "Payload too large")
            return

        if content_length > 0:
            post_data = self.rfile.read(content_length)
            try:
                body = json.loads(post_data)
            except json.JSONDecodeError:
                self._send_error(400, "Malformed JSON")
                return
        else:
            body = {}

        if path.startswith("/v1/customers/") and path.endswith("/audit"):
            import re
            customer_id = path.split("/")[3]
            if not re.match(r'^[a-zA-Z0-9_-]+$', customer_id):
                self._send_error(400, "Invalid customer ID format")
                return
            secure_swarm_protocol.SecureSwarmProtocol.audit_customer_credentials()
            self._send_response(200, {"status": "audit_triggered", "customer_id": customer_id})
            
        elif path == "/v1/events":
            if not isinstance(body, dict):
                self._send_error(400, "Malformed JSON: expected object")
                return
            
            # Log it to customer_db
            customer_db_instance.log_detection_event(
                customer_id=body.get("customer_id", "unknown"),
                event_type=body.get("event_type", "unknown"),
                ip_address=body.get("ip_address") or body.get("ip"),
                ja4_hash=body.get("ja4_hash") or body.get("ja4"),
                bot_class=body.get("bot_class"),
                outcome=body.get("outcome"),
                latency_ms=body.get("latency_ms")
            )
            # "broadcast to daemon" could be simulated or skipped since we don't have daemon code
            
            self._send_response(200, {"status": "event_logged"})
            
        else:
            self._send_error(404, "Not Found")

def main():
    if os.path.exists(SOCKET_PATH):
        os.remove(SOCKET_PATH)
        
    server = UnixHTTPServer(SOCKET_PATH, APIHandler)
    os.chmod(SOCKET_PATH, 0o600)
    print(f"[*] AXIOM ZERO REST API listening on Unix socket: {SOCKET_PATH} (Permissions: 0600)")
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        pass
    finally:
        server.server_close()
        if os.path.exists(SOCKET_PATH):
            os.remove(SOCKET_PATH)

if __name__ == "__main__":
    main()
