from datetime import datetime
from pathlib import Path
from typing import Optional

from flask import Flask, redirect, render_template, request, url_for, flash, session
from flask_sqlalchemy import SQLAlchemy

BASE_DIR = Path(__file__).resolve().parent
DB_PATH = BASE_DIR / "app.db"

db = SQLAlchemy()


def create_app() -> Flask:
    app = Flask(__name__)
    app.config["SECRET_KEY"] = "change-me-in-production"  # session needs this
    app.config["SQLALCHEMY_DATABASE_URI"] = f"sqlite:///{DB_PATH}"
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

    db.init_app(app)

    with app.app_context():
        from models import Submission  # noqa: F401
        db.create_all()

    register_routes(app)

    return app


def register_routes(app: Flask) -> None:
    from models import Submission

    @app.get("/")
    def submit_form():
        return render_template("submit.html")
    
	# --- RESET DATABASE ROUTE ---
    @app.get("/reset-db")
    def reset_db_form():
        """Show a simple page with a reset button."""
        return render_template("reset_db.html")

    @app.post("/reset-db")
    def reset_db_action():
        """Delete all submissions and clear the session."""
        from models import Submission

        # Clear table
        Submission.query.delete()
        db.session.commit()

        # Clear session (so old real_answer etc. are gone)
        session.clear()

        flash("Database has been reset.", "success")
        return redirect(url_for("submit_form"))

    @app.post("/submit")
    def submit():
        name = (request.form.get("name") or "").strip()
        estimate_raw = (request.form.get("estimate") or "").strip()

        if not name:
            flash("Name is required.", "error")
            return redirect(url_for("submit_form"))

        try:
            estimate = int(estimate_raw)
        except ValueError:
            flash("Estimated Syllables must be an integer.", "error")
            return redirect(url_for("submit_form"))

        submission = Submission(
            name=name,
            estimate=estimate,
            created_at=datetime.utcnow(),
        )
        db.session.add(submission)
        db.session.commit()

        flash("Submission received!", "success")
        return redirect(url_for("submit_form"))

    @app.get("/finalize")
    def finalize_form():
        return render_template("finalize.html")

    @app.post("/finalize")
    def finalize():
        real_answer_raw = (request.form.get("real_answer") or "").strip()

        try:
            real_answer = int(real_answer_raw)
        except ValueError:
            flash("Real answer must be an integer.", "error")
            return redirect(url_for("finalize_form"))

        # Save the real answer to session so results() can access it
        session['real_answer'] = real_answer
        session['finalized_at'] = datetime.utcnow().isoformat()

        flash(f"Finalized with real answer = {real_answer}", "success")
        return redirect(url_for("results"))

    @app.get("/results/")
    def results():
        submissions = Submission.query.order_by(Submission.created_at.asc()).all()

        winners = []               # a list of Submission objects (can be empty)
        real_answer = session.get('real_answer')

        if real_answer is not None and submissions:
            # compute the absolute difference for each submission
            def diff(s: Submission) -> int:
                return abs(int(s.estimate) - int(real_answer))

            # find the minimal difference
            diffs = [diff(s) for s in submissions]
            min_diff = min(diffs) if diffs else None

            if min_diff is not None:
                # select all submissions that have that minimal difference
                winners = [s for s in submissions if diff(s) == min_diff]

        return render_template(
            "results.html",
            submissions=submissions,
            winners=winners,
            real_answer=real_answer,
        )

    @app.post("/reset_finalization")
    def reset_finalization():
        session.pop('real_answer', None)
        session.pop('finalized_at', None)
        flash("Finalization cleared.", "success")
        return redirect(url_for("results"))


app = create_app()

if __name__ == "__main__":
    app.run(debug=True)
