"""
Micropub endpoint routes for StarPunk

Implements the W3C Micropub specification for creating posts via
external IndieWeb clients.

Endpoints:
    GET/POST /micropub - Main Micropub endpoint
        GET: Query operations (config, source, syndicate-to)
        POST: Action operations (create in V1, update/delete in future)

Authentication:
    Bearer token authentication required for all endpoints.
    Token must have appropriate scope for requested operation.

References:
    - W3C Micropub Specification: https://www.w3.org/TR/micropub/
    - ADR-028: Micropub Implementation Strategy
    - ADR-029: Micropub IndieAuth Integration Strategy
"""

from flask import Blueprint, current_app, request

from starpunk.micropub import (
    MicropubError,
    extract_bearer_token,
    error_response,
    handle_create,
    handle_query,
)
from starpunk.auth_external import verify_external_token

# Create blueprint
bp = Blueprint("micropub", __name__)


@bp.route("/micropub", methods=["GET", "POST"])
def micropub_endpoint():
    """
    Main Micropub endpoint for all operations

    GET requests:
        Handle query operations via q= parameter:
        - q=config: Return server capabilities
        - q=source&url={url}: Return post source
        - q=syndicate-to: Return syndication targets

    POST requests:
        Handle action operations (form-encoded or JSON):
        - action=create (or no action): Create new post
        - action=update: Update existing post (not supported in V1)
        - action=delete: Delete post (not supported in V1)

    Authentication:
        Requires valid bearer token in Authorization header or
        access_token parameter.

    Returns:
        GET: JSON response with query results
        POST create: 201 Created with Location header
        POST other: Error responses

    Error responses follow OAuth 2.0 format:
        {
            "error": "error_code",
            "error_description": "Human-readable description"
        }
    """
    # Extract and verify token
    token = extract_bearer_token(request)
    if not token:
        return error_response("unauthorized", "No access token provided", 401)

    token_info = verify_external_token(token)
    if not token_info:
        return error_response("unauthorized", "Invalid or expired access token", 401)

    # Handle query endpoints (GET requests)
    if request.method == "GET":
        try:
            return handle_query(request.args.to_dict(), token_info)
        except MicropubError as e:
            return error_response(e.error, e.error_description, e.status_code)
        except Exception as e:
            current_app.logger.error(f"Micropub query error: {e}")
            return error_response("server_error", "An unexpected error occurred", 500)

    # Handle action endpoints (POST requests)
    content_type = request.headers.get("Content-Type", "")

    try:
        # Parse request based on content type
        if "application/json" in content_type:
            data = request.get_json() or {}
            action = data.get("action", "create")
        else:
            # Form-encoded or multipart (V1 only supports form-encoded)
            data = request.form.to_dict(flat=False)
            action = data.get("action", ["create"])[0]

        # Route to appropriate handler
        if action == "create":
            return handle_create(data, token_info)
        elif action == "update":
            # V1: Update not supported
            return error_response(
                "invalid_request", "Update action not supported in V1", 400
            )
        elif action == "delete":
            # V1: Delete not supported
            return error_response(
                "invalid_request", "Delete action not supported in V1", 400
            )
        else:
            return error_response("invalid_request", f"Unknown action: {action}", 400)

    except MicropubError as e:
        return error_response(e.error, e.error_description, e.status_code)
    except Exception as e:
        current_app.logger.error(f"Micropub action error: {e}")
        return error_response("server_error", "An unexpected error occurred", 500)
