from datetime import datetime, timedelta

from flask import (
    Blueprint,
    jsonify,
    request,
    render_template,
    session,
    redirect,
    url_for
)

from sqlalchemy import func

from extensions import db

from models import (
    Order,
    OrderItem,
    Payment
)


performance_bp = Blueprint(
    "performance",
    __name__,
    url_prefix="/admin/performance"
)


@performance_bp.route("/")
def performance_page():

    if "user_id" not in session:
        return redirect(url_for("auth.login"))

    return render_template(
        "admin/performance.html"
    )


@performance_bp.route("/data")
def performance_data():

    if "user_id" not in session:
        return jsonify({
            "error": "Unauthorized"
        }), 401

    period = request.args.get(
        "period",
        "30"
    )

    try:
        period = int(period)
    except (ValueError, TypeError):
        period = 30

    allowed_periods = [
        7,
        30,
        90,
        180,
        365
    ]

    if period not in allowed_periods:
        period = 30

    end_date = datetime.utcnow()

    start_date = (
        end_date
        - timedelta(days=period - 1)
    )


    # =========================================================
    # PAID REVENUE TREND
    # =========================================================

    revenue = (
        db.session.query(
            func.date(
                Payment.created_at
            ).label("date"),
            func.sum(
                Payment.amount
            ).label("revenue")
        )
        .join(
            Order,
            Payment.order_id == Order.id
        )
        .filter(
            Payment.created_at >= start_date,
            Payment.created_at <= end_date,
            Payment.status == "paid",
            Order.order_status != "cancelled"
        )
        .group_by(
            func.date(
                Payment.created_at
            )
        )
        .order_by(
            func.date(
                Payment.created_at
            )
        )
        .all()
    )

    revenue_data = [
        {
            "date": row.date.isoformat(),
            "revenue": float(
                row.revenue or 0
            )
        }
        for row in revenue
    ]


    # =========================================================
    # ORDERS TREND
    # =========================================================

    orders = (
        db.session.query(
            func.date(
                Order.created_at
            ).label("date"),
            func.count(
                Order.id
            ).label("orders")
        )
        .filter(
            Order.created_at >= start_date,
            Order.created_at <= end_date
        )
        .group_by(
            func.date(
                Order.created_at
            )
        )
        .order_by(
            func.date(
                Order.created_at
            )
        )
        .all()
    )

    orders_data = [
        {
            "date": row.date.isoformat(),
            "orders": int(
                row.orders
            )
        }
        for row in orders
    ]


    # =========================================================
    # BEST-SELLING PRODUCTS
    # =========================================================

    top_products = (
        db.session.query(
            OrderItem.product_name,
            func.sum(
                OrderItem.quantity
            ).label("quantity")
        )
        .join(
            Order,
            OrderItem.order_id == Order.id
        )
        .filter(
            Order.created_at >= start_date,
            Order.created_at <= end_date,
            Order.order_status != "cancelled"
        )
        .group_by(
            OrderItem.product_name
        )
        .order_by(
            func.sum(
                OrderItem.quantity
            ).desc()
        )
        .limit(10)
        .all()
    )

    top_products_data = [
        {
            "product": row.product_name,
            "quantity": int(
                row.quantity or 0
            )
        }
        for row in top_products
    ]


    # =========================================================
    # PRODUCT SALES VALUE
    # =========================================================

    product_revenue = (
        db.session.query(
            OrderItem.product_name,
            func.sum(
                OrderItem.subtotal
            ).label("revenue")
        )
        .join(
            Order,
            OrderItem.order_id == Order.id
        )
        .filter(
            Order.created_at >= start_date,
            Order.created_at <= end_date,
            Order.order_status != "cancelled"
        )
        .group_by(
            OrderItem.product_name
        )
        .order_by(
            func.sum(
                OrderItem.subtotal
            ).desc()
        )
        .limit(10)
        .all()
    )

    product_revenue_data = [
        {
            "product": row.product_name,
            "revenue": float(
                row.revenue or 0
            )
        }
        for row in product_revenue
    ]


    # =========================================================
    # ORDER STATUS
    # =========================================================

    order_status = (
        db.session.query(
            Order.order_status,
            func.count(
                Order.id
            ).label("count")
        )
        .filter(
            Order.created_at >= start_date,
            Order.created_at <= end_date
        )
        .group_by(
            Order.order_status
        )
        .all()
    )

    order_status_data = [
        {
            "status": row.order_status or "unknown",
            "count": int(
                row.count
            )
        }
        for row in order_status
    ]


    # =========================================================
    # PAYMENT METHODS
    # =========================================================

    payment_methods = (
        db.session.query(
            Payment.payment_method,
            func.sum(
                Payment.amount
            ).label("amount")
        )
        .join(
            Order,
            Payment.order_id == Order.id
        )
        .filter(
            Payment.created_at >= start_date,
            Payment.created_at <= end_date,
            Payment.status == "paid",
            Order.order_status != "cancelled"
        )
        .group_by(
            Payment.payment_method
        )
        .all()
    )

    payment_method_data = [
        {
            "method": row.payment_method or "unknown",
            "amount": float(
                row.amount or 0
            )
        }
        for row in payment_methods
    ]


    # =========================================================
    # TOTAL PAID REVENUE
    # =========================================================

    total_revenue = (
        db.session.query(
            func.coalesce(
                func.sum(
                    Payment.amount
                ),
                0
            )
        )
        .join(
            Order,
            Payment.order_id == Order.id
        )
        .filter(
            Payment.created_at >= start_date,
            Payment.created_at <= end_date,
            Payment.status == "paid",
            Order.order_status != "cancelled"
        )
        .scalar()
    )

    total_revenue = float(
        total_revenue or 0
    )


    # =========================================================
    # PAID ORDERS
    # =========================================================

    paid_orders = (
        db.session.query(
            func.count(
                func.distinct(
                    Payment.order_id
                )
            )
        )
        .join(
            Order,
            Payment.order_id == Order.id
        )
        .filter(
            Payment.created_at >= start_date,
            Payment.created_at <= end_date,
            Payment.status == "paid",
            Order.order_status != "cancelled"
        )
        .scalar()
    )

    paid_orders = int(
        paid_orders or 0
    )


    # =========================================================
    # TOTAL ORDERS
    # =========================================================

    total_orders = (
        db.session.query(
            func.count(
                Order.id
            )
        )
        .filter(
            Order.created_at >= start_date,
            Order.created_at <= end_date
        )
        .scalar()
    )

    total_orders = int(
        total_orders or 0
    )


    # =========================================================
    # AVERAGE PAID ORDER
    # =========================================================

    average_paid_order = (
        total_revenue / paid_orders
        if paid_orders > 0
        else 0
    )


    # =========================================================
    # RESPONSE
    # =========================================================

    return jsonify({

        "period": period,

        "summary": {

            "revenue": total_revenue,

            "orders": total_orders,

            "paid_orders": paid_orders,

            "average_paid_order": round(
                average_paid_order,
                2
            )
        },

        "revenue": revenue_data,

        "orders": orders_data,

        "top_products": top_products_data,

        "product_revenue": product_revenue_data,

        "order_status": order_status_data,

        "payment_methods": payment_method_data

    })