"""Dashboard routes - main landing page."""
from __future__ import annotations

from flask import Blueprint, render_template
from flask_login import login_required, current_user
from sqlalchemy import func

from app.extensions import db
from app.models.asset import Asset, AssetProfile
from app.models.watchlist import Watchlist
from app.models.signal import TradingSignal
from app.models.portfolio import Portfolio
from app.helpers.asset_filter import apply_asset_filter
from app.helpers.auth import get_current_user_id

dashboard_bp = Blueprint('dashboard', __name__)


@dashboard_bp.route('/')
def index():
    """Landing page for guests, dashboard for authenticated users."""
    # ── Public landing page for unauthenticated visitors ──
    if not current_user.is_authenticated:
        from app.helpers.tier_config import get_tier_pricing, get_all_features
        from app.helpers.landing_content import get_landing_content
        pricing = get_tier_pricing()
        features = get_all_features()
        landing = get_landing_content()
        # Count features per category
        cat_counts = {}
        tier_raw = {}
        for f in features:
            cat_counts[f.category] = cat_counts.get(f.category, 0) + 1
            tier_raw[f.min_tier] = tier_raw.get(f.min_tier, 0) + 1
        # Cumulative tier counts (each tier includes all lower tiers)
        tier_counts = {
            'free': tier_raw.get('free', 0),
            'starter': tier_raw.get('free', 0) + tier_raw.get('starter', 0),
            'pro': tier_raw.get('free', 0) + tier_raw.get('starter', 0) + tier_raw.get('pro', 0),
            'ultimate': sum(tier_raw.values()),
        }
        return render_template('landing.html',
                               pricing=pricing,
                               tier_counts=tier_counts,
                               category_counts=cat_counts,
                               total_features=len(features),
                               landing=landing)

    # ── Admin redirect to admin panel ──
    from app.models.admin import Admin
    if isinstance(current_user._get_current_object(), Admin):
        from flask import redirect
        return redirect('/admin/')

    # ── Authenticated dashboard ──
    from app.helpers.asset_filter import get_asset_mode
    asset_mode = get_asset_mode()

    # --- Collect data sources (filtered by asset_mode) ---
    watchlist = Watchlist.query.join(Asset, Watchlist.asset_id == Asset.id)\
        .filter(Watchlist.user_id == get_current_user_id(),
                Asset.asset_type == asset_mode)\
        .order_by(Watchlist.display_order.asc()).all()
    positions = Portfolio.query.join(Asset, Portfolio.asset_id == Asset.id)\
        .filter(Portfolio.user_id == get_current_user_id(),
                Asset.asset_type == asset_mode, Portfolio.total_quantity > 0).all()
    signals = TradingSignal.query.join(Asset, TradingSignal.asset_id == Asset.id)\
        .filter(Asset.asset_type == asset_mode, TradingSignal.status == 'active')\
        .order_by(TradingSignal.created_at.desc()).limit(20).all()

    # --- Batch load assets and profiles (fix N+1) ---
    all_asset_ids = list(set(
        [w.asset_id for w in watchlist] + [p.asset_id for p in positions]
    ))

    coins_map = {}
    profiles_map = {}

    if all_asset_ids:
        # Batch load assets
        coins_map = {
            c.id: c for c in
            Asset.query.filter(Asset.id.in_(all_asset_ids)).all()
        }

        # Batch load latest profiles per asset via subquery
        latest_sq = db.session.query(
            AssetProfile.asset_id,
            func.max(AssetProfile.fetched_at).label('max_f')
        ).filter(
            AssetProfile.asset_id.in_(all_asset_ids)
        ).group_by(AssetProfile.asset_id).subquery()

        profiles = AssetProfile.query.join(
            latest_sq,
            db.and_(
                AssetProfile.asset_id == latest_sq.c.asset_id,
                AssetProfile.fetched_at == latest_sq.c.max_f,
            )
        ).all()
        profiles_map = {p.asset_id: p for p in profiles}

    # --- Build chart_coins (deduplicated, ordered: watchlist first, then portfolio-only) ---
    seen_ids = set()
    chart_coins = []
    for w in watchlist:
        if w.asset_id not in seen_ids:
            seen_ids.add(w.asset_id)
            asset = coins_map.get(w.asset_id)
            chart_coins.append({
                'id': w.asset_id,
                'symbol': asset.symbol if asset else w.asset_id,
                'name': asset.name if asset else w.asset_id,
                'icon_thumb_url': asset.icon_thumb_url if asset else None,
                'asset_type': asset.asset_type if asset else 'crypto',
            })
    for p in positions:
        if p.asset_id not in seen_ids:
            seen_ids.add(p.asset_id)
            asset = coins_map.get(p.asset_id)
            chart_coins.append({
                'id': p.asset_id,
                'symbol': asset.symbol if asset else p.asset_id,
                'name': asset.name if asset else p.asset_id,
                'icon_thumb_url': asset.icon_thumb_url if asset else None,
                'asset_type': asset.asset_type if asset else 'crypto',
            })

    # --- Portfolio summary ---
    portfolio_items = []
    total_invested = 0.0
    total_current = 0.0
    total_realized = 0.0

    for p in positions:
        qty = float(p.total_quantity or 0)
        avg_buy = float(p.avg_buy_price or 0)
        invested = float(p.total_invested_idr or 0)
        realized = float(p.realized_pnl or 0)

        profile = profiles_map.get(p.asset_id)
        current_price = float(profile.current_price_idr) if profile and profile.current_price_idr else 0
        current_value = current_price * qty
        unrealized = current_value - (avg_buy * qty) if avg_buy > 0 else 0

        asset = coins_map.get(p.asset_id)
        portfolio_items.append({
            'asset_id': p.asset_id,
            'asset': asset,
            'coin_symbol': asset.symbol.upper() if asset else p.asset_id.upper(),
            'quantity': qty,
            'avg_buy_price': avg_buy,
            'current_price': current_price,
            'current_value': round(current_value, 2),
            'unrealized_pnl': round(unrealized, 2),
            'realized_pnl': realized,
        })

        total_invested += invested
        total_current += current_value
        total_realized += realized

    total_unrealized = total_current - total_invested
    total_return_pct = ((total_current - total_invested) / total_invested * 100) if total_invested > 0 else 0

    portfolio_summary = {
        'count': len(portfolio_items),
        'total_invested': round(total_invested, 2),
        'total_current': round(total_current, 2),
        'total_unrealized': round(total_unrealized, 2),
        'total_realized': round(total_realized, 2),
        'total_return_pct': round(total_return_pct, 2),
    }

    # --- Watchlist with prices ---
    watchlist_data = []
    for w in watchlist:
        profile = profiles_map.get(w.asset_id)
        asset = coins_map.get(w.asset_id)
        watchlist_data.append({
            'asset_id': w.asset_id,
            'asset': asset,
            'notes': w.notes,
            'price': float(profile.current_price_idr) if profile and profile.current_price_idr else None,
            'change_24h': float(profile.price_change_24h) if profile and profile.price_change_24h else None,
            'change_7d': float(profile.price_change_7d) if profile and profile.price_change_7d else None,
        })

    # --- Counts ---
    total_tracked = apply_asset_filter(Asset.query.filter_by(is_active=True)).count()
    active_signal_count = TradingSignal.query.join(Asset, TradingSignal.asset_id == Asset.id)\
        .filter(Asset.asset_type == asset_mode, TradingSignal.status == 'active').count()

    return render_template('dashboard/index.html',
                           chart_coins=chart_coins,
                           watchlist=watchlist,
                           watchlist_data=watchlist_data,
                           signals=signals,
                           portfolio_items=portfolio_items,
                           portfolio_summary=portfolio_summary,
                           total_tracked=total_tracked,
                           active_signal_count=active_signal_count)
