"""Application factory."""
import os

from flask import Flask

from . import storage
from .config import Config


def create_app(config_object=None):
    base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    frontend_dir = os.path.join(base_dir, "frontend")

    app = Flask(
        __name__,
        template_folder=os.path.join(frontend_dir, "templates"),
        static_folder=os.path.join(frontend_dir, "static"),
    )
    app.config.from_object(config_object or Config)

    storage.init_storage(app.config["STORAGE_DIR"])

    from .auth import auth_bp, init_auth
    from .tasks import tasks_bp
    from .admin import admin_bp
    from .reports import reports_bp
    from .notifications import init_notifications, notifications_bp

    init_auth(app)
    init_notifications(app)
    app.register_blueprint(auth_bp)
    app.register_blueprint(tasks_bp)
    app.register_blueprint(admin_bp)
    app.register_blueprint(reports_bp)
    app.register_blueprint(notifications_bp)

    _register_service_worker(app)
    _register_error_handlers(app)
    _register_template_helpers(app)
    return app


def _register_service_worker(app):
    from flask import make_response

    @app.route("/sw.js")
    def service_worker():
        resp = make_response(app.send_static_file("sw.js"))
        resp.headers["Service-Worker-Allowed"] = "/"
        resp.headers["Cache-Control"] = "no-cache"
        return resp


def _register_error_handlers(app):
    from flask import render_template

    @app.errorhandler(403)
    def forbidden(e):
        return render_template("error.html", code=403,
                               message="You don't have access to this page."), 403

    @app.errorhandler(404)
    def not_found(e):
        return render_template("error.html", code=404,
                               message="Page not found."), 404


def _register_template_helpers(app):
    from datetime import datetime

    from .timeutils import to_ist, today_ist

    @app.template_filter("nicedate")
    def nicedate(value):
        """Format a YYYY-MM-DD string as e.g. 'Mon, 05 Jul 2026'."""
        if not value:
            return "No due date"
        try:
            return datetime.strptime(value, "%Y-%m-%d").strftime("%a, %d %b %Y")
        except ValueError:
            return value

    @app.template_filter("nicedatetime")
    def nicedatetime(value):
        """Render a stored UTC timestamp in IST, e.g. '05 Jul 2026, 21:30'."""
        dt = to_ist(value)
        if dt is None:
            return ""
        return dt.strftime("%d %b %Y, %H:%M")

    @app.context_processor
    def inject_today():
        return {"today": today_ist()}

    @app.context_processor
    def inject_notifications():
        from flask_login import current_user

        if current_user.is_authenticated:
            return {"notif_unread": storage.unread_count(current_user.id)}
        return {"notif_unread": 0}
