from flask import Flask, request, jsonify, send_from_directory
import os

app = Flask(__name__)

@app.route('/')
def help():
    help_text = '''
    <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>API Help</title>
</head>
<body>
    <h1>API Help</h1>
    <p>This API demonstrates various aspects of API design, including:</p>
    <ol>
        <li>GET /greet?name=&lt;name&gt; - Query parameter example. Replace &lt;name&gt; with your name to get a greeting.</li>
        <li>GET /math/&lt;int:num1&gt;/&lt;int:num2&gt; - URL parameter example. Replace &lt;num1&gt; and &lt;num2&gt; with integers for a simple addition result.</li>
        <li>POST /reverse - JSON body parameter example. Send a JSON object with a "text" field to get the text reversed.</li>
        <li>GET /dir/subdir - Directory and subdirectory example. An example of nested directories in API design.</li>
        <li>GET /headers - Header parameter example. Send custom header 'X-Api-Key' to see the header value in response.</li>
        <li>PUT /update - PUT method example. Send a JSON object with 'id' and 'value' fields to update an item in a simple in-memory store.</li>
        <li>GET /search?query=&lt;query&gt;&amp;offset=&lt;offset&gt;&amp;limit=&lt;limit&gt; - Optional query parameters example. Replace &lt;query&gt; with your search term, &lt;offset&gt; with the number of items to skip, and &lt;limit&gt; with the number of items to return.</li>
        <li>POST /upload - File upload example. Send a file with the field name 'file' to upload it to the server.</li>
        <li>GET /files/&lt;filename&gt; - File download example. Replace &lt;filename&gt; with the name of the file you uploaded to download it.</li>
    </ol>
</body>
</html>
    '''
    return help_text

@app.route('/greet')
def greet():
    name = request.args.get('name', 'Stranger')
    return f'Hello, {name}!'

@app.route('/math/<int:num1>/<int:num2>')
def math(num1, num2):
    result = num1 + num2
    return jsonify({"result": result})

@app.route('/reverse', methods=['POST'])
def reverse():
    data = request.get_json()
    text = data.get('text', '')
    reversed_text = text[::-1]
    return jsonify({"reversed_text": reversed_text})

@app.route('/dir/subdir')
def dir_subdir():
    return "Welcome to the /dir/subdir endpoint!"

@app.route('/headers')
def headers():
    api_key = request.headers.get('X-Api-Key', 'Not provided')
    return jsonify({"X-Api-Key": api_key})

store = {}

@app.route('/update', methods=['PUT'])
def update():
    data = request.get_json()
    item_id = data.get('id')
    value = data.get('value')

    if item_id and value:
        store[item_id] = value
        return jsonify({"message": "Item updated successfully", "item": {item_id: value}})
    else:
        return jsonify({"message": "Invalid request data"}), 400
    
@app.route('/search')
def search():
    query = request.args.get('query', '')
    offset = int(request.args.get('offset', 0))
    limit = int(request.args.get('limit', 10))

    # Simulate a list of search results
    all_results = [f'Result {i} for {query}' for i in range(1, 101)]
    paginated_results = all_results[offset:offset + limit]

    return jsonify({"results": paginated_results, "offset": offset, "limit": limit})

UPLOAD_FOLDER = 'uploaded_files'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

if not os.path.exists(UPLOAD_FOLDER):
    os.makedirs(UPLOAD_FOLDER)

@app.route('/upload', methods=['POST'])
def upload():
    if 'file' not in request.files:
        return jsonify({"message": "No file part"}), 400

    file = request.files['file']
    if file.filename == '':
        return jsonify({"message": "No file selected"}), 400

    file.save(os.path.join(app.config['UPLOAD_FOLDER'], file.filename))
    return jsonify({"message": "File uploaded successfully", "filename": file.filename})

@app.route('/files/<filename>')
def download(filename):
    return send_from_directory(app.config['UPLOAD_FOLDER'], filename)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5023)
