"""Export API endpoints."""
from __future__ import annotations

import io
import zipfile
from datetime import date

from flask import Blueprint, jsonify, request, Response
from app.helpers.auth import admin_required
from sqlalchemy import func

from app.services.export.csv_exporter import export_ohlcv_csv, export_profile_json
from app.services.export.json_exporter import (
    export_signals_json, export_timeline_json, export_portfolio_json,
)

api_export_bp = Blueprint('api_export', __name__)


@api_export_bp.route('/ohlcv/<asset_id>/<timeframe>')
@admin_required
def export_ohlcv(asset_id, timeframe):
    """Export OHLCV data as CSV download with optional date filter."""
    source = request.args.get('source')
    start_date = request.args.get('start_date')
    end_date = request.args.get('end_date')

    csv_content = export_ohlcv_csv(asset_id, timeframe, source,
                                   start_date=start_date, end_date=end_date)

    from app.helpers.asset_id import get_raw_id
    filename = f"{get_raw_id(asset_id).upper()}_IDR_{timeframe}.csv"
    return Response(
        csv_content,
        mimetype='text/csv',
        headers={'Content-Disposition': f'attachment; filename={filename}'}
    )


@api_export_bp.route('/ohlcv-bulk')
@admin_required
def export_ohlcv_bulk():
    """Export multiple OHLCV datasets as ZIP.

    Query params:
        asset_ids: comma-separated asset IDs
        timeframes: comma-separated timeframes
        start_date, end_date: optional YYYY-MM-DD filters
    """
    asset_ids = request.args.get('asset_ids', '').split(',')
    timeframes = request.args.get('timeframes', '').split(',')
    start_date = request.args.get('start_date')
    end_date = request.args.get('end_date')
    source = request.args.get('source')

    asset_ids = [c.strip() for c in asset_ids if c.strip()]
    timeframes = [t.strip() for t in timeframes if t.strip()]

    if not asset_ids or not timeframes:
        return jsonify({'error': 'asset_ids and timeframes are required'}), 400

    # Build ZIP in memory
    zip_buffer = io.BytesIO()
    with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zf:
        for asset_id in asset_ids:
            for tf in timeframes:
                csv_content = export_ohlcv_csv(asset_id, tf, source,
                                               start_date=start_date, end_date=end_date)
                if csv_content.count('\n') > 1:  # Has data (header + at least 1 row)
                    from app.helpers.asset_id import get_raw_id
                    filename = f"{get_raw_id(asset_id).upper()}_IDR_{tf}.csv"
                    zf.writestr(filename, csv_content)

    zip_buffer.seek(0)
    return Response(
        zip_buffer.getvalue(),
        mimetype='application/zip',
        headers={'Content-Disposition': 'attachment; filename=koinkamu_ohlcv_export.zip'}
    )


@api_export_bp.route('/ohlcv-count')
@admin_required
def export_ohlcv_count():
    """Get record count for OHLCV export preview.

    Query params: asset_ids, timeframes, start_date, end_date
    """
    from app.models.ohlcv import OHLCVData
    from app.models.settings import AppSettings
    from datetime import datetime

    asset_ids = request.args.get('asset_ids', '').split(',')
    timeframes = request.args.get('timeframes', '').split(',')
    start_date = request.args.get('start_date')
    end_date = request.args.get('end_date')
    from app.helpers.asset_filter import get_active_data_source
    source = request.args.get('source') or get_active_data_source()

    asset_ids = [c.strip() for c in asset_ids if c.strip()]
    timeframes = [t.strip() for t in timeframes if t.strip()]

    if not asset_ids or not timeframes:
        return jsonify({'count': 0})

    query = OHLCVData.query.filter(
        OHLCVData.asset_id.in_(asset_ids),
        OHLCVData.timeframe.in_(timeframes),
        OHLCVData.source == source,
    )

    if start_date:
        try:
            sd = datetime.strptime(start_date, '%Y-%m-%d')
            query = query.filter(OHLCVData.datetime_wib >= sd)
        except ValueError:
            pass

    if end_date:
        try:
            ed = datetime.strptime(end_date, '%Y-%m-%d').replace(hour=23, minute=59, second=59)
            query = query.filter(OHLCVData.datetime_wib <= ed)
        except ValueError:
            pass

    count = query.count()
    return jsonify({'count': count})


@api_export_bp.route('/profile/<asset_id>')
@admin_required
def export_profile(asset_id):
    """Export asset profile as JSON download."""
    json_content = export_profile_json(asset_id)

    from app.helpers.asset_id import get_raw_id
    filename = f"{get_raw_id(asset_id).upper()}_profile.json"
    return Response(
        json_content,
        mimetype='application/json',
        headers={'Content-Disposition': f'attachment; filename={filename}'}
    )


@api_export_bp.route('/signals')
@admin_required
def export_signals():
    """Export trading signals as JSON download."""
    asset_id = request.args.get('asset_id')
    status = request.args.get('status')
    limit = request.args.get('limit', 50, type=int)

    json_content = export_signals_json(asset_id, status, limit)

    from app.helpers.asset_id import get_raw_id
    suffix = f"_{get_raw_id(asset_id).upper()}" if asset_id else ""
    filename = f"signals{suffix}.json"
    return Response(
        json_content,
        mimetype='application/json',
        headers={'Content-Disposition': f'attachment; filename={filename}'}
    )


@api_export_bp.route('/timeline/<asset_id>')
@admin_required
def export_timeline(asset_id):
    """Export prediction queue as JSON download."""
    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

    json_content = export_timeline_json(asset_id, pred_date)

    from app.helpers.asset_id import get_raw_id
    filename = f"timeline_{get_raw_id(asset_id).upper()}_{pred_date or date.today()}.json"
    return Response(
        json_content,
        mimetype='application/json',
        headers={'Content-Disposition': f'attachment; filename={filename}'}
    )


@api_export_bp.route('/portfolio')
@admin_required
def export_portfolio():
    """Export full portfolio as JSON download."""
    json_content = export_portfolio_json()

    filename = "portfolio_export.json"
    return Response(
        json_content,
        mimetype='application/json',
        headers={'Content-Disposition': f'attachment; filename={filename}'}
    )
