from flask import Flask, request, jsonify, render_template, make_response, send_from_directory
from litellm import completion
import os
import json
from datetime import datetime
import base64
from llm_utils import generate_completion
import re

app = Flask(__name__)

# Use an environment variable for the upload folder, with a default to /tmp/uploads
UPLOAD_FOLDER = os.environ.get('UPLOAD_FOLDER', '/tmp/uploads')

# Ensure the upload folder exists
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
@app.route('/favicon.ico')
def favicon():
    return send_from_directory(os.path.join(app.root_path, 'static'),
                               'favicon.ico', mimetype='image/vnd.microsoft.icon')
@app.route('/')
def index():
    recent_files = get_recent_files()
    response = make_response(render_template('index.html', recent_files=recent_files))
    return response

def get_recent_files():
    if not os.path.exists(app.config['UPLOAD_FOLDER']):
        os.makedirs(app.config['UPLOAD_FOLDER'])
    files = os.listdir(app.config['UPLOAD_FOLDER'])
    valid_files = [f for f in files if f.lower().endswith(('.pdf', '.txt'))]
    valid_files.sort(key=lambda x: os.path.getmtime(os.path.join(app.config['UPLOAD_FOLDER'], x)), reverse=True)
    return [{'filename': file, 'date': datetime.fromtimestamp(os.path.getmtime(os.path.join(app.config['UPLOAD_FOLDER'], file))).isoformat()} for file in valid_files[:5]]

@app.route('/get_recent_files')
def get_recent_files_route():
    return jsonify(get_recent_files())

@app.route('/upload_file', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return jsonify({'error': 'No file part'}), 400
    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': 'No selected file'}), 400
    if file and (file.filename.lower().endswith(('.pdf', '.txt', '.epub'))):
        filename = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
        file.save(filename)
        return jsonify({'message': 'File uploaded successfully', 'filename': file.filename}), 200
    return jsonify({'error': 'Invalid file type. Please upload a PDF, TXT, or EPUB file.'}), 400

@app.route('/get_epub_content/<path:filename>')
def get_epub_content(filename):
    file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
    if os.path.exists(file_path) and filename.endswith('.epub'):
        with open(file_path, 'rb') as file:
            epub_content = base64.b64encode(file.read()).decode('utf-8')
        return jsonify({'epub_content': epub_content})
    return jsonify({'error': 'File not found or not an EPUB'}), 404

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

@app.route('/generate_flashcard', methods=['POST'])
def generate_flashcard():
    data = request.json
    prompt = data['prompt']
    mode = data.get('mode', 'flashcard')
    model = data.get('model')

    try:
        # Use llm_utils to generate completion with the selected model
        content = generate_completion(prompt, model=model)
        print(prompt)
        print(content)

        if mode == 'language':
            try:
                # Extract the JSON substring from the content in case there is extra text.
                json_match = re.search(r'\{[\s\S]*\}', content)
                if json_match:
                    json_text = json_match.group(0)
                    flashcard = json.loads(json_text)
                    return jsonify({'flashcard': flashcard})
                else:
                    raise ValueError("No JSON object found in response")
            except Exception as parse_err:
                print("JSON parsing error in language mode: ", parse_err)
                return jsonify({'error': 'JSON parsing error in language mode: ' + str(parse_err)})
        elif mode == 'flashcard':
            try:
                # Extract the JSON array substring from the content in case there is extra text.
                json_match = re.search(r'\[[\s\S]*\]', content)
                if json_match:
                    json_text = json_match.group(0)
                    flashcards = json.loads(json_text)
                    return jsonify({'flashcards': flashcards})
                else:
                    raise ValueError("No JSON array found in response")
            except Exception as parse_err:
                return jsonify({'error': 'JSON parsing error in flashcard mode: ' + str(parse_err)})
        elif mode == 'explain':
            try:
                # Try loading JSON with an "explanation" key; fallback to plain text if not provided
                parsed = json.loads(content)
                explanation = parsed.get('explanation', content)
                return jsonify({'explanation': explanation})
            except Exception as parse_err:
                return jsonify({'explanation': content})
        else:
            return jsonify({'error': 'Invalid mode'}), 400

    except Exception as e:
        return jsonify({'error': str(e)}), 500
if __name__ == '__main__':
    # Use environment variables to determine the run mode
    debug_mode = os.environ.get('FLASK_DEBUG', 'False').lower() == 'true'
    app.run(debug=debug_mode, host='0.0.0.0', port=7860)