import os
from flask import Flask, jsonify, send_from_directory
from auth import require_token
from functions import user_service, exercise_service, feedback_service, muscle_service, notification_service, request_service, task_service, workout_service, calendar_service, statistic_service, muscle_card_service, user_stat_service, equipment_service, friendship_service, message_service
from functions.statistic_service import track_usage
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

#UTILITIES
app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 2 * 1024 * 1024
limiter = Limiter(key_func=get_remote_address)
limiter.init_app(app)

@app.errorhandler(413)
def too_large(e):
    return jsonify({"error": "File too large. Max size is 2MB."}), 413

@app.route("/")
def index():
    try:
        path = os.path.join(os.path.dirname(__file__), "docs", "index.html")
        return open(path, encoding="utf-8").read()
    except Exception as e:
        return f"<h1>500 Internal Server Error</h1><p>{str(e)}</p>", 500

@app.route('/docs/assets/<path:filename>')
def serve_assets(filename):
    return send_from_directory(os.path.join("docs", "assets"), filename)

@app.errorhandler(404)
def not_found(e):
    return jsonify({"error": "Route not found"}), 404

#STATISTIC SERVICE
@app.route("/stats/api_usage", methods=["GET"])
@require_token
def usage_stats():
    data, status = statistic_service.get_api_usage()
    return jsonify(data), status
#USER SERVICE
@app.route("/users/id/<int:user_id>", methods=["GET"])
@require_token
@track_usage
def get_user_by_id(user_id):
    return user_service.get_user_by_id(user_id)

@app.route("/users/username/<string:username>", methods=["GET"])
@require_token
@track_usage
def get_user_by_username(username):
    return user_service.get_user_by_username(username)

@app.route("/users/search/<string:name>", methods=["GET"])
@require_token
@track_usage
def get_users_by_display_name(name):
    return user_service.get_users_by_display_name(name)

@app.route("/users/register", methods=["POST"])
@track_usage
@limiter.limit("5 per minute")
def register_user():
    return user_service.register_user()


@app.route("/users/login", methods=["POST"])
@track_usage
@limiter.limit("10 per minute")
def login_user():
    return user_service.login_user()

@app.route("/users/delete", methods=["POST"])
@require_token
@track_usage
def delete_user():
    return user_service.delete_user()

@app.route("/users/filter", methods=["GET"])
@require_token
@track_usage
def filter_users():
    return user_service.filter_users()

@app.route("/users/upload_pfp", methods=["POST"])
@require_token
@track_usage
def upload_pfp():
    return user_service.upload_profile_picture()

@app.route("/users/get_pfp/<string:username>", methods=["GET"])
@track_usage
def get_profile_picture(username):
    return user_service.get_profile_picture(username)

@app.route("/users/update", methods=["POST"])
@require_token
@track_usage
def update_user_field():
    return user_service.update_user_field()

#EXERCISE SERVICE
@app.route("/exercises", methods=["GET"])
@require_token
@track_usage
def get_exercises():
    return exercise_service.get_exercises()

@app.route("/exercises/create", methods=["POST"])
@require_token
@track_usage
def create_exercise():
    return exercise_service.create_exercise()

@app.route("/exercises/delete", methods=["POST"])
@require_token
@track_usage
def delete_exercise():
    return exercise_service.delete_exercise()

@app.route("/exercises/filter", methods=["GET"])
@require_token
@track_usage
def filter_exercises():
    return exercise_service.filter_exercises()

@app.route("/exercises/upload_image", methods=["POST"])
@require_token
@track_usage
def upload_exercise_image():
    return exercise_service.upload_exercise_image()

@app.route("/exercises/update", methods=["POST"])
@require_token
@track_usage
def update_exercise_field():
    return exercise_service.update_exercise_field()

#FEEDBACK SERVICE
@app.route("/feedbacks", methods=["GET"])
@require_token
@track_usage
def get_feedbacks():
    return feedback_service.get_all_feedbacks()

@app.route("/feedbacks/submit", methods=["POST"])
@require_token
@track_usage
@limiter.limit("5 per minute")
def submit_feedback():
    return feedback_service.submit_feedback()

@app.route("/feedbacks/delete", methods=["POST"])
@require_token
@track_usage
def delete_feedback():
    return feedback_service.delete_feedback()

#MUSCLE_SERVICE
@app.route("/muscles/<string:muscle_name>", methods=["GET"])
@require_token
@track_usage
def get_muscle_by_name(muscle_name):
    return muscle_service.get_muscle_by_name(muscle_name)

@app.route("/muscles", methods=["GET"])
@require_token
@track_usage
def get_all_muscles():
    return muscle_service.get_all_muscles()

@app.route("/muscles/update", methods=["POST"])
@require_token
@track_usage
def update_muscle_field():
    return muscle_service.update_muscle_field()

#EQUIPMENT SERVICE
@app.route('/equipments', methods=['GET'])
@require_token
@track_usage
def get_equipments():
    return equipment_service.get_all_equipments()

@app.route('/equipments/create', methods=['POST'])
@require_token
@track_usage
def create_equipment():
    return equipment_service.create_equipment()

@app.route('/equipments/delete', methods=['POST'])
@require_token
@track_usage
def delete_equipment():
    return equipment_service.delete_equipment()

@app.route('/equipments/update', methods=['POST'])
@require_token
@track_usage
def update_equipment():
    return equipment_service.update_equipment_field()

#NOTIFICATION SERVICE
@app.route("/notifications/send", methods=["POST"])
@require_token
@track_usage
def send_notification():
    return notification_service.send_notification()

@app.route("/notifications/<int:user_id>", methods=["GET"])
@require_token
@track_usage
def get_user_notifications(user_id):
    return notification_service.get_notifications_for_user(user_id)

@app.route("/notifications/delete", methods=["POST"])
@require_token
@track_usage
def delete_notification():
    return notification_service.delete_notification()

#REQUEST SERVICE
@app.route("/requests", methods=["GET"])
@require_token
@track_usage
def get_requests():
    return request_service.get_all_requests()

@app.route("/requests/submit", methods=["POST"])
@require_token
@track_usage
@limiter.limit("5 per minute")
def submit_request():
    return request_service.submit_request()

@app.route("/requests/accept", methods=["POST"])
@require_token
@track_usage
def accept_request():
    return request_service.accept_request()

@app.route("/requests/reject", methods=["POST"])
@require_token
@track_usage
def reject_request():
    return request_service.reject_request()

#TASK SERVICE
@app.route("/tasks", methods=["GET"])
@require_token
@track_usage
def get_tasks():
    return task_service.get_all_tasks()

@app.route("/tasks/create", methods=["POST"])
@require_token
@track_usage
def create_task():
    return task_service.create_task()

@app.route("/tasks/delete", methods=["POST"])
@require_token
@track_usage
def delete_task():
    return task_service.delete_task()

@app.route("/tasks/update", methods=["POST"])
@require_token
@track_usage
def update_task():
    return task_service.update_task_field()

#WORKOUT SERVICE
@app.route("/workouts", methods=["GET"])
@require_token
@track_usage
def get_workouts_by_user():
    return workout_service.get_workouts_by_user()

@app.route("/workouts/create", methods=["POST"])
@require_token
@track_usage
@limiter.limit("5 per minute")
def create_workout():
    return workout_service.create_workout()

@app.route("/workouts/delete", methods=["POST"])
@require_token
@track_usage
def delete_workout():
    return workout_service.delete_workout()

@app.route("/workouts/modify_exercise", methods=["POST"])
@require_token
@track_usage
@limiter.limit("10 per minute")
def modify_workout_exercise():
    return workout_service.modify_workout_exercise()

@app.route("/workouts/update", methods=["POST"])
@require_token
@track_usage
@limiter.limit("10 per minute")
def update_workout_field():
    return workout_service.update_workout_field()

#CALENDAR SERVICE
@app.route("/calendars", methods=["GET"])
@require_token
@track_usage
def get_calendar():
    return calendar_service.get_calendar_by_user()

@app.route("/calendars/day", methods=["GET"])
@require_token
@track_usage
def get_calendar_day():
    return calendar_service.get_calendar_for_day()

@app.route("/calendars/schedule", methods=["POST"])
@require_token
@track_usage
def schedule_workout():
    return calendar_service.add_calendar_entry()

@app.route("/calendars/delete", methods=["POST"])
@require_token
@track_usage
def delete_calendar_entry():
    return calendar_service.delete_calendar_entry()

#MUSCLE CARD SERVICE
@app.route("/muscle_cards", methods=["GET"])
@require_token
@track_usage
def get_all_muscle_scores():
    return muscle_card_service.get_muscle_cards_for_user()

@app.route("/muscle_cards/score", methods=["GET"])
@require_token
@track_usage
def get_muscle_score():
    return muscle_card_service.get_muscle_score()

@app.route("/muscle_cards/set", methods=["POST"])
@require_token
@track_usage
def set_muscle_score():
    return muscle_card_service.set_muscle_score()

@app.route("/muscle_cards/reset", methods=["POST"])
@require_token
@track_usage
@limiter.limit("3 per minute")
def reset_muscle_scores():
    return muscle_card_service.reset_muscle_scores()

#USER STAT SERVICE
@app.route("/user_stats", methods=["GET"])
@require_token
@track_usage
def get_user_stats():
    return user_stat_service.get_user_stats()

@app.route("/user_stats/create", methods=["POST"])
@require_token
@track_usage
@limiter.limit("5 per minute")
def create_user_stat():
    return user_stat_service.create_user_stat()

@app.route("/user_stats/update", methods=["POST"])
@require_token
@track_usage
def update_user_stat():
    return user_stat_service.update_user_stat()

@app.route("/user_stats/delete", methods=["POST"])
@require_token
@track_usage
def delete_user_stat():
    return user_stat_service.delete_user_stat()

@app.route("/user_stats/entry", methods=["POST"])
@require_token
@track_usage
def add_stat_entry():
    return user_stat_service.add_stat_entry()

@app.route("/user_stats/entries", methods=["GET"])
@require_token
@track_usage
def get_stat_entries():
    return user_stat_service.get_stat_entries()

@app.route("/user_stats/entry/update", methods=["POST"])
@require_token
@track_usage
def update_stat_entry():
    return user_stat_service.update_stat_entry()

@app.route("/user_stats/entry/delete", methods=["POST"])
@require_token
@track_usage
def delete_stat_entry():
    return user_stat_service.delete_stat_entry()

@app.route("/user_stats/entry/latest", methods=["GET"])
@require_token
@track_usage
def get_latest_stat_entry():
    return user_stat_service.get_latest_stat_entry()

#FRIENDSHIP SERVICE
@app.route("/friends", methods=["GET"])
@require_token
@track_usage
def get_friends():
    return friendship_service.get_friends()

@app.route("/friends/request", methods=["POST"])
@require_token
@track_usage
def send_friend_request():
    return friendship_service.send_friend_request()

@app.route("/friends/accept", methods=["POST"])
@require_token
@track_usage
def accept_friend_request():
    return friendship_service.accept_friend_request()

@app.route("/friends/block", methods=["POST"])
@require_token
@track_usage
def block_friend():
    return friendship_service.block_friend()

@app.route("/friends/remove", methods=["POST"])
@require_token
@track_usage
def remove_friend():
    return friendship_service.remove_friend()

#MESSAGE SERVICE
@app.route("/messages/send", methods=["POST"])
@require_token
@track_usage
def send_message():
    return message_service.send_message()

@app.route("/messages/delete", methods=["POST"])
@require_token
@track_usage
def delete_message():
    return message_service.delete_message()

@app.route("/messages/conversation", methods=["GET"])
@require_token
@track_usage
def get_conversation():
    return message_service.get_conversation()
