import os
import traceback
from datetime import datetime

from dotenv import load_dotenv
from flask import Flask, flash, redirect, render_template, request, session, url_for

from db import execute, fetch_all, fetch_one, get_public_config
from recommendations import build_recommendations


load_dotenv()


CAUSE_OPTIONS = [
    ("hunger", "Hunger and food access"),
    ("housing", "Housing and homelessness"),
    ("education", "Education and mentoring"),
    ("health", "Health and mental health"),
    ("environment", "Environment and climate"),
    ("animals", "Animal welfare"),
    ("arts", "Arts and culture"),
    ("justice", "Civil rights and legal aid"),
    ("disaster", "Disaster relief"),
    ("veterans", "Veterans and military families"),
]

SUPPORT_OPTIONS = [
    ("money", "Donate money"),
    ("time", "Volunteer time"),
    ("skills", "Donate professional skills"),
    ("goods", "Donate goods or supplies"),
]


def create_app():
    app = Flask(__name__)
    app.secret_key = os.getenv("FLASK_SECRET_KEY", "dev-secret-change-me")

    @app.errorhandler(Exception)
    def show_debug_error(error):
        if os.getenv("SHOW_DETAILED_ERRORS", "false").lower() != "true":
            raise error

        return (
            render_template(
                "error.html",
                error=error,
                traceback_text=traceback.format_exc(),
            ),
            500,
        )

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

    @app.get("/health/db")
    def database_health():
        config = get_public_config()
        row = fetch_one("SELECT 1 AS ok")
        return {"connection": "connected", "config": config, "ok": row["ok"]}

    @app.route("/register", methods=["GET", "POST"])
    def register():
        if request.method == "POST":
            form = request.form
            name = form.get("name", "").strip()
            email = form.get("email", "").strip().lower()
            mobile = form.get("mobile", "").strip()
            sms_consent = "sms_consent" in form
            email_consent = "email_consent" in form

            selected_causes = form.getlist("causes")
            selected_support = form.getlist("support_types")
            location = form.get("location", "").strip()
            budget = form.get("budget", "").strip()
            availability = form.get("availability", "").strip()
            motivation = form.get("motivation", "").strip()

            errors = []
            if not name:
                errors.append("Name is required.")
            if not email or "@" not in email:
                errors.append("A valid email is required.")
            if mobile and len(mobile) < 7:
                errors.append("Please enter a valid mobile number.")
            if not selected_causes:
                errors.append("Choose at least one cause area.")
            if not selected_support:
                errors.append("Choose at least one way you want to help.")

            if errors:
                for error in errors:
                    flash(error, "error")
                return render_template(
                    "register.html",
                    cause_options=CAUSE_OPTIONS,
                    support_options=SUPPORT_OPTIONS,
                    form=form,
                    selected_causes=selected_causes,
                    selected_support=selected_support,
                )

            user_id = execute(
                """
                INSERT INTO users
                    (name, email, mobile, sms_consent, email_consent, created_at)
                VALUES
                    (%s, %s, %s, %s, %s, %s)
                """,
                (name, email, mobile or None, sms_consent, email_consent, datetime.utcnow()),
            )

            execute(
                """
                INSERT INTO user_preferences
                    (user_id, causes, support_types, location, budget, availability, motivation)
                VALUES
                    (%s, %s, %s, %s, %s, %s, %s)
                """,
                (
                    user_id,
                    ",".join(selected_causes),
                    ",".join(selected_support),
                    location or None,
                    budget or None,
                    availability or None,
                    motivation or None,
                ),
            )

            session["user_id"] = user_id
            return redirect(url_for("recommendations"))

        return render_template(
            "register.html",
            cause_options=CAUSE_OPTIONS,
            support_options=SUPPORT_OPTIONS,
            form={},
            selected_causes=[],
            selected_support=[],
        )

    @app.get("/recommendations")
    def recommendations():
        user_id = session.get("user_id")
        if not user_id:
            flash("Create an account first so recommendations can be tailored to you.", "error")
            return redirect(url_for("register"))

        user = fetch_one("SELECT * FROM users WHERE id = %s", (user_id,))
        preferences = fetch_one(
            "SELECT * FROM user_preferences WHERE user_id = %s ORDER BY id DESC LIMIT 1",
            (user_id,),
        )
        charities = fetch_all("SELECT * FROM charities WHERE active = TRUE")

        results = build_recommendations(preferences, charities)

        for rank, result in enumerate(results, start=1):
            execute(
                """
                INSERT INTO recommendation_history
                    (user_id, charity_id, rank_position, score, explanation, created_at)
                VALUES
                    (%s, %s, %s, %s, %s, %s)
                """,
                (
                    user_id,
                    result["charity"]["id"],
                    rank,
                    result["score"],
                    result["explanation"],
                    datetime.utcnow(),
                ),
            )

        return render_template(
            "recommendations.html",
            user=user,
            preferences=preferences,
            recommendations=results,
        )

    @app.get("/charities")
    def charities():
        rows = fetch_all("SELECT * FROM charities WHERE active = TRUE ORDER BY name")
        return render_template("charities.html", charities=rows)

    return app


app = create_app()


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