"""
# File: pyapi/app/routes/api.py
# Description: API routes for the OTT Reports service, including caching, validation, and error handling
"""

from datetime import datetime
from flask import Blueprint, jsonify, request
from app.utils.helpers import get_logger, performance_log
from app.decorators.validation import validate_json, validate_query, validate_multiple
from app.schemas.request_schemas import (
    ProphetTrainRequest,
    ProphetForecastRequest,
    ProphetPlotRequest,
    ProphetValidateRequest,
    RegressionTrainRequest,
    CollectionRiskScoreRequest,
    SalesTargetPredictRequest,
)
from app.services.cache_service import CacheService, cache_response
from app.middleware.auth_middleware import auth_middleware
from app.controllers.prophet_controller import ProphetController
from app.controllers.report_controller import ReportController
from app.controllers.regression_controller import RegressionController

api_bp = Blueprint("api", __name__)
logger = get_logger("api")


# =================================================================
# CACHING STRATEGY IMPLEMENTATION
#
# This API uses SINGLE-LAYER caching at the route level:
#
# ✅ Route-level caching (@cache_response):
#    - Caches complete API responses including JSON serialization
#    - Includes request parameters in cache key automatically
#    - Simple to manage and debug
#    - Consistent cache behavior across all endpoints
#
# ❌ Controller-level caching (removed):
#    - Previously caused double caching
#    - Created cache inconsistency issues
#    - Increased memory usage unnecessarily
#
# 🔧 Database query caching:
#    - Only used for expensive sub-queries within same request
#    - Helper methods available but should be used sparingly
#
# Cache Keys Format:
# - Route level: "api_endpoint_name:{hash_of_request_params}"
# - Database level: "mongo_collection_name:{hash_of_query}"
# =================================================================


@api_bp.route("/health", methods=["GET"])
@performance_log
@cache_response("health_check", timeout=60)  # Cache health check for 1 minute
def health_check():
    """Health check endpoint with cache statistics"""
    try:
        # Get basic health status
        health_data = {
            "status": "healthy",
            "timestamp": str(datetime.now()),
            "cache": CacheService.get_stats(),
        }

        # Test database connections (cached for performance)
        report_controller = ReportController()
        db_health_response = report_controller.get_database_health()

        # Extract JSON data from the Response object
        if hasattr(db_health_response, "get_json"):
            # For Flask Response objects
            health_data["databases"] = db_health_response.get_json()
        elif hasattr(db_health_response, "json"):
            # Alternative method for Response objects
            health_data["databases"] = db_health_response.json
        elif isinstance(db_health_response, tuple) and len(db_health_response) >= 1:
            # If it returns a tuple (response, status_code), get the response part
            response_data = db_health_response[0]
            if hasattr(response_data, "get_json"):
                health_data["databases"] = response_data.get_json()
            else:
                health_data["databases"] = {
                    "status": "unknown",
                    "error": "Unable to parse database health response",
                }
        else:
            # Fallback: assume it's already a dictionary
            health_data["databases"] = db_health_response

        response = jsonify(health_data)
        response.status_code = 200
        return response

    except Exception as e:
        logger.error(f"Health check failed: {str(e)}")
        response = jsonify(
            {"status": "unhealthy", "error": str(e), "timestamp": str(datetime.now())}
        )
        response.status_code = 500
        return response


""" @api_bp.route("/reports/channel-access-code/redeem/count", methods=["GET"])
# @validate_query(ChannelAccessCodeRedemptionRequest)
@cache_response(
    "channel_access_code_redeem_count", timeout=300
)  # Single cache at route level
def get_channel_access_code_redemption_count(validated_query):
    "Endpoint to get the count of users who have redeemed channel access code with validation"
    report_controller = ReportController()
    return report_controller.get_channel_access_code_redeem_count(validated_query)
 """

@api_bp.route("/data", methods=["POST"])
def create_data():
    data = request.json
    ### audit_log("data_processed", details={"items_count": len(data)})
    """ return jsonify({
            "status": "success",
            "result": result,
            "request_id": g.request_id
        }) """
    # Here you would typically call a service to handle the data
    response = jsonify({"message": "Data created", "data": data})
    response.status_code = 201
    return response


@api_bp.route("/data/<int:data_id>", methods=["GET"])
def get_data(data_id):
    """
    Endpoint to retrieve data by ID
    This is a placeholder for demonstration purposes.
    In a real application, you would retrieve data from a database or service.
    """
    # Here you would typically retrieve data from a database or service
    response = jsonify({"data_id": data_id, "data": "Sample data"})
    response.status_code = 200
    return response


@api_bp.route("/data/<int:data_id>", methods=["DELETE"])
def delete_data(data_id):
    """
    Endpoint to delete data by ID
    This is a placeholder for demonstration purposes.
    In a real application, you would delete data from a database or service.
    """
    # Here you would typically call a service to delete the data
    response = jsonify({"message": "Data deleted", "data_id": data_id})
    response.status_code = 204
    return response


@api_bp.route("/cache/stats", methods=["GET"])
@performance_log
def get_cache_stats():
    """Get cache statistics"""
    try:
        stats = CacheService.get_stats()
        response = jsonify(
            {"status": "success", "data": stats, "timestamp": str(datetime.now())}
        )
        response.status_code = 200
        return response
    except Exception as e:
        logger.error(f"Error getting cache stats: {str(e)}")
        response = jsonify({"status": "error", "message": str(e)})
        response.status_code = 500
        return response


@api_bp.route("/cache/clear", methods=["POST"])
@auth_middleware.require_api_key
@performance_log
def clear_cache():
    """Clear all cache (admin endpoint)"""
    try:
        success = CacheService.clear()
        response = jsonify(
            {
                "status": "success" if success else "warning",
                "message": "Cache cleared successfully"
                if success
                else "Cache clear may have failed",
                "timestamp": str(datetime.now()),
            }
        )
        response.status_code = 200
        return response
    except Exception as e:
        logger.error(f"Error clearing cache: {str(e)}")
        response = jsonify({"status": "error", "message": str(e)})
        response.status_code = 500
        return response


@api_bp.route("/reports/database/health", methods=["GET"])
def get_reports_database_health():
    """Database connectivity health check"""
    controller = ReportController()
    return controller.get_database_health()


# =================================================================
# PROPHET FORECASTING ENDPOINTS
# =================================================================

@api_bp.route("/prophet/train", methods=["POST"])
@auth_middleware.require_api_key
@validate_json(ProphetTrainRequest)
def train_prophet_model(validated_json):
    """Train a Prophet forecasting model"""
    controller = ProphetController()
    return controller.train_model(validated_json)


@api_bp.route("/prophet/forecast/<model_id>", methods=["POST"])
@auth_middleware.require_api_key
@validate_json(ProphetForecastRequest)
def generate_prophet_forecast(model_id, validated_json):
    """Generate forecast using a trained Prophet model"""
    controller = ProphetController()
    return controller.generate_forecast(model_id, validated_json)


@api_bp.route("/prophet/plot/<model_id>", methods=["POST"])
@auth_middleware.require_api_key
@validate_json(ProphetPlotRequest)
def generate_prophet_plot(model_id, validated_json):
    """Generate forecast plot for a trained Prophet model"""
    controller = ProphetController()
    return controller.get_forecast_plot(model_id, validated_json)


@api_bp.route("/prophet/models/<model_id>", methods=["GET"])
@auth_middleware.require_api_key
def get_prophet_model_info(model_id):
    """Get information about a trained Prophet model"""
    controller = ProphetController()
    return controller.get_model_info(model_id)


@api_bp.route("/prophet/models", methods=["GET"])
@auth_middleware.require_api_key
def list_prophet_models():
    """List all trained Prophet models"""
    controller = ProphetController()
    return controller.list_models()


@api_bp.route("/prophet/models/<model_id>", methods=["DELETE"])
@auth_middleware.require_api_key
def delete_prophet_model(model_id):
    """Delete a trained Prophet model"""
    controller = ProphetController()
    return controller.delete_model(model_id)


@api_bp.route("/prophet/validate", methods=["POST"])
@auth_middleware.require_api_key
@validate_json(ProphetValidateRequest)
def validate_prophet_data(validated_json):
    """Validate time series data format for Prophet"""
    controller = ProphetController()
    return controller.validate_data(validated_json)


# =================================================================
# PROPHET DATABASE INTEGRATION ENDPOINTS
# =================================================================

@api_bp.route("/prophet/train/db", methods=["POST"])
@auth_middleware.require_api_key
def train_prophet_from_database():
    """Train a Prophet model using data from OMS database"""
    controller = ProphetController()
    data = request.get_json(silent=True) or {}
    return controller.train_from_database(data)


@api_bp.route("/prophet/tables", methods=["GET"])
@auth_middleware.require_api_key
def get_prophet_tables():
    """Get available OMS tables for time series analysis"""
    controller = ProphetController()
    return controller.get_available_tables()


@api_bp.route("/prophet/tables/<table_key>/preview", methods=["GET"])
@auth_middleware.require_api_key
def get_prophet_data_preview(table_key):
    """Get preview of time series data from a table"""
    controller = ProphetController()
    params = request.args.to_dict()
    return controller.get_data_preview(table_key, params)


@api_bp.route("/prophet/tables/<table_key>/validate", methods=["GET"])
@auth_middleware.require_api_key
def validate_prophet_table(table_key):
    """Validate a table configuration"""
    controller = ProphetController()
    return controller.validate_table_config(table_key)


# =================================================================
# REGRESSION / CLASSIFICATION ENDPOINTS
# =================================================================

@api_bp.route("/regression/train/collection-risk", methods=["POST"])
@auth_middleware.require_api_key
@validate_json(RegressionTrainRequest)
def train_collection_risk_model(validated_json):
    """Train XGBoost collection risk classifier for a company"""
    controller = RegressionController()
    return controller.train_collection_risk(validated_json)


@api_bp.route("/regression/train/sales-target", methods=["POST"])
@auth_middleware.require_api_key
@validate_json(RegressionTrainRequest)
def train_sales_target_model(validated_json):
    """Train XGBoost sales target attainment regressor for a company"""
    controller = RegressionController()
    return controller.train_sales_target(validated_json)


@api_bp.route("/regression/score/collection-risk", methods=["POST"])
@auth_middleware.require_api_key
@validate_json(CollectionRiskScoreRequest)
def score_collection_risk(validated_json):
    """Score clients for payment delay probability"""
    controller = RegressionController()
    return controller.score_collection_risk(validated_json)


@api_bp.route("/regression/predict/sales-target", methods=["POST"])
@auth_middleware.require_api_key
@validate_json(SalesTargetPredictRequest)
def predict_sales_target(validated_json):
    """Predict attainment % for district×product_head combinations"""
    controller = RegressionController()
    return controller.predict_sales_target(validated_json)


@api_bp.route("/regression/models", methods=["GET"])
@auth_middleware.require_api_key
def list_regression_models():
    """List all trained regression/classification models"""
    controller = RegressionController()
    return controller.list_models()


@api_bp.route("/regression/models/<model_id>", methods=["GET"])
@auth_middleware.require_api_key
def get_regression_model_info(model_id):
    """Get info for a specific regression model"""
    controller = RegressionController()
    return controller.get_model_info(model_id)


@api_bp.route("/regression/models/<model_id>", methods=["DELETE"])
@auth_middleware.require_api_key
def delete_regression_model(model_id):
    """Delete a regression model"""
    controller = RegressionController()
    return controller.delete_model(model_id)


@api_bp.errorhandler(404)
def not_found(error):
    logger.warning(f"404 error for path: {request.path}")
    response = jsonify({"error": "Endpoint not found"})
    response.status_code = 404
    return response


@api_bp.errorhandler(405)
def method_not_allowed(error):
    logger.warning(f"405 error for {request.method} {request.path}")
    response = jsonify({"error": "Method not allowed"})
    response.status_code = 405
    return response


@api_bp.errorhandler(Exception)
def handle_api_exception(error):
    """Catch any unhandled exceptions in API routes and ensure JSON response"""
    logger.error(f"Unhandled API exception: {str(error)}")
    response = jsonify(
        {
            "error": "Internal server error",
            "message": "An unexpected error occurred",
        }
    )
    response.status_code = 500
    return response
