"""Timeline API endpoints."""
from flask import Blueprint, jsonify, request
from flask_login import login_required
from app.extensions import db

api_timeline_bp = Blueprint('api_timeline', __name__)

_generator = None


def _get_generator():
    global _generator
    if _generator is None:
        from app.services.timeline import TimelineGenerator
        _generator = TimelineGenerator()
    return _generator


@api_timeline_bp.route('/generate/<asset_id>')
@login_required
def generate_timeline(asset_id):
    """Generate a prediction queue for a asset.

    Query params:
        timeframe: OHLCV timeframe (default: 1h)
        source: Data source
        date: Prediction date (YYYY-MM-DD, default: today)
    """
    from datetime import date

    timeframe = request.args.get('timeframe', '1h')
    source = request.args.get('source')
    date_str = request.args.get('date')

    pred_date = None
    if date_str:
        try:
            pred_date = date.fromisoformat(date_str)
        except ValueError:
            return jsonify({'error': 'Invalid date format, use YYYY-MM-DD'}), 400

    gen = _get_generator()
    result = gen.generate(asset_id, pred_date, timeframe, source)
    return jsonify(result)


@api_timeline_bp.route('/generate/<asset_id>/save', methods=['POST'])
@login_required
def generate_and_save(asset_id):
    """Generate and save prediction queue to database."""
    from datetime import date

    timeframe = request.args.get('timeframe', '1h')
    source = request.args.get('source')
    date_str = request.args.get('date')

    pred_date = None
    if date_str:
        try:
            pred_date = date.fromisoformat(date_str)
        except ValueError:
            return jsonify({'error': 'Invalid date format'}), 400

    gen = _get_generator()
    result = gen.generate(asset_id, pred_date, timeframe, source)
    count = gen.save_queue(result)

    return jsonify({
        'saved': count,
        'asset_id': asset_id,
        'prediction_date': result['prediction_date'],
        'summary': result['summary'],
    })


@api_timeline_bp.route('/queue/<asset_id>')
@login_required
def get_queue(asset_id):
    """Get saved prediction queue for a asset and date."""
    from app.models.prediction_queue import PredictionQueue
    from datetime import date

    date_str = request.args.get('date')
    if date_str:
        try:
            pred_date = date.fromisoformat(date_str)
        except ValueError:
            return jsonify({'error': 'Invalid date format'}), 400
    else:
        pred_date = date.today()

    entries = PredictionQueue.query.filter_by(
        asset_id=asset_id,
        prediction_date=pred_date,
    ).order_by(PredictionQueue.sequence_num.asc()).all()

    return jsonify({
        'asset_id': asset_id,
        'prediction_date': str(pred_date),
        'queue': [e.to_dict() for e in entries],
        'total': len(entries),
    })


@api_timeline_bp.route('/history/<asset_id>')
@login_required
def get_history(asset_id):
    """Get prediction queue history for a asset."""
    from app.models.prediction_queue import PredictionQueue
    from sqlalchemy import func

    limit = request.args.get('limit', 7, type=int)

    # Get distinct dates with entries
    dates = PredictionQueue.query.with_entities(
        PredictionQueue.prediction_date,
        func.count(PredictionQueue.id).label('entry_count'),
        func.sum(PredictionQueue.profit).label('total_profit'),
    ).filter_by(
        asset_id=asset_id,
    ).group_by(
        PredictionQueue.prediction_date,
    ).order_by(
        PredictionQueue.prediction_date.desc(),
    ).limit(limit).all()

    history = []
    for d in dates:
        history.append({
            'date': str(d.prediction_date),
            'entry_count': d.entry_count,
            'total_profit': float(d.total_profit) if d.total_profit else 0,
        })

    return jsonify({
        'asset_id': asset_id,
        'history': history,
    })


@api_timeline_bp.route('/queue/<int:entry_id>/execute', methods=['PUT'])
@login_required
def execute_queue_entry(entry_id):
    """Mark a queue entry as executed and create the corresponding portfolio trade."""
    from app.models.prediction_queue import PredictionQueue
    from app.services.portfolio import PortfolioService

    entry = PredictionQueue.query.get(entry_id)
    if not entry:
        return jsonify({'error': 'Queue entry not found'}), 404
    if entry.is_executed:
        return jsonify({'error': 'Already executed'}), 400

    # Mark as executed
    entry.is_executed = True

    # Create the trade in portfolio (service commits the session)
    svc = PortfolioService()
    trade_result = svc.execute_trade(
        asset_id=entry.asset_id,
        side=entry.action,
        price=float(entry.predicted_price),
        quantity=float(entry.quantity),
        signal_id=None,
        is_simulation=True,
    )

    return jsonify({
        'executed': entry_id,
        'trade': trade_result,
    })


@api_timeline_bp.route('/queue/<int:entry_id>', methods=['DELETE'])
@login_required
def delete_queue_entry(entry_id):
    """Delete/cancel a queue entry."""
    from app.models.prediction_queue import PredictionQueue

    entry = PredictionQueue.query.get(entry_id)
    if not entry:
        return jsonify({'error': 'Queue entry not found'}), 404

    db.session.delete(entry)
    db.session.commit()
    return jsonify({'deleted': entry_id})
