import http.server, json, re, threading
from datetime import datetime, timezone
from urllib.parse import urlparse, parse_qs

LOCK = threading.Lock()
TYPES = {"auto", "home", "health", "life", "travel"}
STATUSES = {"submitted", "in_review", "approved", "denied", "paid", "closed"}

def now_iso():
    return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")

CLAIMS = {}
SEQ = [1002]  # last-used numeric suffix; next_id() starts at CLM-1003

for _c in [
    {"id": "CLM-1001", "policyNumber": "POL-88231", "claimant": "Jane Doe", "type": "auto",
     "status": "in_review", "amount": 4200.50, "currency": "USD", "incidentDate": "2026-08-14",
     "description": "Rear-end collision on I-90", "createdAt": "2026-08-15T09:24:00Z"},
    {"id": "CLM-1002", "policyNumber": "POL-77410", "claimant": "Carlos Mendez", "type": "home",
     "status": "approved", "amount": 15230.00, "currency": "USD", "incidentDate": "2026-07-30",
     "description": "Water damage from a burst pipe", "createdAt": "2026-07-31T14:02:00Z"},
]:
    CLAIMS[_c["id"]] = _c

def next_id():
    SEQ[0] += 1
    return "CLM-%d" % SEQ[0]

class H(http.server.BaseHTTPRequestHandler):
    def log_message(self, *a): pass
    def _send(self, code, obj=None):
        body = b"" if obj is None else json.dumps(obj).encode()
        self.send_response(code)
        if obj is not None:
            self.send_header("Content-Type", "application/json")
            self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        if body:
            self.wfile.write(body)
    def _read_json(self):
        n = int(self.headers.get("Content-Length") or 0)
        if n == 0:
            return {}
        try:
            return json.loads(self.rfile.read(n) or b"{}")
        except Exception:
            return None
    def _id(self):
        m = re.fullmatch(r"/claims/([^/]+)", urlparse(self.path).path)
        return m.group(1) if m else None

    def do_GET(self):
        p = urlparse(self.path)
        if p.path == "/claims":
            q = parse_qs(p.query)
            status = q.get("status", [None])[0]
            policy = q.get("policyNumber", [None])[0]
            with LOCK:
                items = list(CLAIMS.values())
            if status:
                items = [c for c in items if c.get("status") == status]
            if policy:
                items = [c for c in items if c.get("policyNumber") == policy]
            return self._send(200, items)
        cid = self._id()
        if cid:
            with LOCK:
                c = CLAIMS.get(cid)
            return self._send(200, c) if c else self._send(404, {"error": "claim not found"})
        self._send(404, {"error": "not found"})

    def do_POST(self):
        if urlparse(self.path).path != "/claims":
            return self._send(404, {"error": "not found"})
        body = self._read_json()
        if body is None:
            return self._send(400, {"error": "invalid JSON body"})
        missing = [f for f in ("policyNumber", "claimant", "type", "incidentDate") if not body.get(f)]
        if missing:
            return self._send(400, {"error": "missing required fields", "fields": missing})
        if body.get("type") not in TYPES:
            return self._send(400, {"error": "invalid type", "allowed": sorted(TYPES)})
        with LOCK:
            cid = next_id()
            claim = {
                "id": cid, "policyNumber": body["policyNumber"], "claimant": body["claimant"],
                "type": body["type"], "status": "submitted",
                "amount": body.get("amount"), "currency": body.get("currency", "USD"),
                "incidentDate": body["incidentDate"], "description": body.get("description", ""),
                "createdAt": now_iso(),
            }
            CLAIMS[cid] = claim
        self._send(201, claim)

    def do_PUT(self):
        cid = self._id()
        if not cid:
            return self._send(404, {"error": "not found"})
        body = self._read_json()
        if body is None:
            return self._send(400, {"error": "invalid JSON body"})
        with LOCK:
            c = CLAIMS.get(cid)
            if not c:
                return self._send(404, {"error": "claim not found"})
            if "status" in body:
                if body["status"] not in STATUSES:
                    return self._send(400, {"error": "invalid status", "allowed": sorted(STATUSES)})
                c["status"] = body["status"]
            if "amount" in body:
                c["amount"] = body["amount"]
            if "description" in body:
                c["description"] = body["description"]
            c["updatedAt"] = now_iso()
            out = dict(c)
        self._send(200, out)

    def do_DELETE(self):
        cid = self._id()
        if not cid:
            return self._send(404, {"error": "not found"})
        with LOCK:
            existed = CLAIMS.pop(cid, None)
        if existed:
            return self._send(204, None)
        self._send(404, {"error": "claim not found"})

http.server.ThreadingHTTPServer(("0.0.0.0", 4010), H).serve_forever()
