#!/usr/bin/env python3
"""
Middleware — rate limiting, CORS, and access logging
Sprint 2-3: HRT-28
"""

import logging
import time
from collections import defaultdict
from datetime import datetime, timezone
from functools import wraps
from threading import Lock

from flask import request, jsonify, g

logger = logging.getLogger("turf_saas.middleware")

# ──────────────────────────────────────────────────────────────
# In-memory rate limiter (100 req/min per IP)
# For production: replace with Redis-backed counter
# ──────────────────────────────────────────────────────────────

_rate_store: dict = defaultdict(lambda: {"count": 0, "window_start": 0.0})
_rate_lock = Lock()

RATE_LIMIT = 100  # max requests
RATE_WINDOW = 60  # seconds


def rate_limit_middleware(app):
    """Register before_request rate limiting on the Flask app."""

    @app.before_request
    def check_rate_limit():
        ip = request.remote_addr or "unknown"
        now = time.time()

        with _rate_lock:
            bucket = _rate_store[ip]
            if now - bucket["window_start"] >= RATE_WINDOW:
                bucket["count"] = 0
                bucket["window_start"] = now
            bucket["count"] += 1
            count = bucket["count"]
            remaining = max(0, RATE_LIMIT - count)

        if count > RATE_LIMIT:
            logger.warning("Rate limit exceeded for IP %s", ip)
            resp = jsonify({"error": "Trop de requêtes. Limite: 100/min par IP."})
            resp.status_code = 429
            resp.headers["X-RateLimit-Limit"] = str(RATE_LIMIT)
            resp.headers["X-RateLimit-Remaining"] = "0"
            resp.headers["Retry-After"] = str(RATE_WINDOW)
            return resp

        # Attach headers on all responses via after_request
        g.rl_remaining = remaining


# ──────────────────────────────────────────────────────────────
# Access logs (timestamped)
# ──────────────────────────────────────────────────────────────

access_log = logging.getLogger("turf_saas.access")


def access_log_middleware(app):
    """Register after_request access logging on the Flask app."""

    @app.after_request
    def log_access(response):
        ip = request.remote_addr or "unknown"
        ts = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
        user_id = getattr(g, "current_user_id", "-")
        access_log.info(
            '%s %s %s "%s %s" %s %s',
            ts,
            ip,
            user_id,
            request.method,
            request.path,
            response.status_code,
            response.content_length or 0,
        )
        # Attach rate-limit headers
        remaining = getattr(g, "rl_remaining", None)
        if remaining is not None:
            response.headers["X-RateLimit-Limit"] = str(RATE_LIMIT)
            response.headers["X-RateLimit-Remaining"] = str(remaining)
        return response
