"""Public API Blueprint: API key management and public endpoints.

Prefix: /api/v1
"""

from flask import Blueprint, request, jsonify, g
from middleware import require_auth
from tenant_db import get_tenant_conn, get_master_conn
from services.public_api_engine import (
    create_api_key, validate_api_key, check_rate_limit, increment_rate_limit,
    log_api_request, list_api_keys, revoke_api_key, delete_api_key,
)

public_api_bp = Blueprint('public_api', __name__, url_prefix='/api/v1')


# ─── Admin endpoints (require auth) ─────────────────────────────

@public_api_bp.route('/keys', methods=['GET'])
@require_auth()
def get_keys():
    conn = get_tenant_conn(g.tenant_id)
    try:
        keys = list_api_keys(conn, g.tenant_id)
        return jsonify({'keys': keys})
    finally:
        conn.close()


@public_api_bp.route('/keys', methods=['POST'])
@require_auth()
def create_key():
    data = request.get_json() or {}
    if not data.get('name'):
        return jsonify({'error': 'name is required'}), 400
    conn = get_tenant_conn(g.tenant_id)
    try:
        key_id, full_key = create_api_key(
            conn, g.tenant_id, data['name'],
            scopes=data.get('scopes', ['read']),
            rate_limit_rpm=data.get('rate_limit_rpm', 60),
            rate_limit_rpd=data.get('rate_limit_rpd', 10000),
            created_by=getattr(g, 'employee_id', None),
            expires_at=data.get('expires_at'),
        )
        return jsonify({
            'id': key_id,
            'api_key': full_key,  # Only shown once!
            'message': 'Store this key safely — it will not be shown again',
        }), 201
    finally:
        conn.close()


@public_api_bp.route('/keys/<int:key_id>/revoke', methods=['PUT'])
@require_auth()
def revoke_key(key_id):
    conn = get_tenant_conn(g.tenant_id)
    try:
        revoke_api_key(conn, key_id)
        return jsonify({'message': 'API key revoked'})
    finally:
        conn.close()


@public_api_bp.route('/keys/<int:key_id>', methods=['DELETE'])
@require_auth()
def delete_key(key_id):
    conn = get_tenant_conn(g.tenant_id)
    try:
        delete_api_key(conn, key_id)
        return jsonify({'message': 'API key deleted'})
    finally:
        conn.close()


# ─── Public endpoints (API key auth) ─────────────────────────────

def _require_api_key():
    """Decorator-like helper to validate API key from header."""
    api_key = request.headers.get('X-API-Key') or request.headers.get('Authorization', '').replace('Bearer ', '')
    if not api_key:
        return None, {'error': 'API key required. Provide via X-API-Key header or Authorization: Bearer <key>'}, 401

    conn = get_master_conn()
    try:
        key_info = validate_api_key(conn, api_key)
        if not key_info or not key_info.get('valid'):
            reason = key_info.get('reason', 'invalid') if key_info else 'invalid'
            return None, {'error': f'API key {reason}'}, 401

        # Check rate limit
        allowed, headers = check_rate_limit(conn, key_info['key_id'], key_info['rate_limit_rpm'], key_info['rate_limit_rpd'])
        if not allowed:
            return None, {'error': 'Rate limit exceeded'}, 429, headers

        increment_rate_limit(conn, key_info['key_id'])
        return key_info, None, None, headers
    finally:
        conn.close()


@public_api_bp.route('/health', methods=['GET'])
def public_health():
    return jsonify({'status': 'ok', 'service': 'Nexus Public API'})


@public_api_bp.route('/catalog/search', methods=['GET'])
def public_catalog_search():
    key_info, error, status, *extra = _require_api_key()
    if error:
        headers = extra[0] if extra else {}
        return jsonify(error), status, headers

    q = request.args.get('q', '').strip()
    limit = min(int(request.args.get('limit', 50)), 200)
    if not q or len(q) < 2:
        return jsonify({'error': 'Query must be at least 2 characters'}), 400

    start_time = __import__('time').time()
    conn = get_tenant_conn(key_info['tenant_id'])
    try:
        from services.catalog_service import smart_search
        master = get_master_conn()
        try:
            results = smart_search(master, q, conn, branch_id=None, limit=limit)
        finally:
            master.close()

        response_time_ms = int((__import__('time').time() - start_time) * 1000)

        # Log the request
        master2 = get_master_conn()
        try:
            log_api_request(
                master2, key_info['key_id'], key_info['tenant_id'],
                request.method, request.path, 200,
                response_time_ms, request.remote_addr,
                request.headers.get('User-Agent'),
            )
        finally:
            master2.close()

        headers = extra[0] if extra else {}
        return jsonify({
            'query': q,
            'results': results,
            'count': len(results),
        }), 200, headers
    finally:
        conn.close()


@public_api_bp.route('/catalog/parts/<int:part_id>', methods=['GET'])
def public_part_detail(part_id):
    key_info, error, status, *extra = _require_api_key()
    if error:
        headers = extra[0] if extra else {}
        return jsonify(error), status, headers

    start_time = __import__('time').time()
    conn = get_tenant_conn(key_info['tenant_id'])
    try:
        cur = conn.cursor()
        cur.execute("""
            SELECT id, part_number, name, brand, price_1, price_2, price_3,
                   image_url, description, is_active
            FROM inventory WHERE id = %s AND is_active = true
        """, (part_id,))
        row = cur.fetchone()
        cur.close()

        if not row:
            return jsonify({'error': 'Part not found'}), 404

        part = {
            'id': row[0], 'part_number': row[1], 'name': row[2],
            'brand': row[3], 'price_1': float(row[4]) if row[4] else None,
            'price_2': float(row[5]) if row[5] else None,
            'price_3': float(row[6]) if row[6] else None,
            'image_url': row[7], 'description': row[8], 'is_active': row[9],
        }

        response_time_ms = int((__import__('time').time() - start_time) * 1000)
        master = get_master_conn()
        try:
            log_api_request(
                master, key_info['key_id'], key_info['tenant_id'],
                request.method, request.path, 200,
                response_time_ms, request.remote_addr,
                request.headers.get('User-Agent'),
            )
        finally:
            master.close()

        headers = extra[0] if extra else {}
        return jsonify(part), 200, headers
    finally:
        conn.close()
