import os
from functools import wraps

from flask import (
    Flask, render_template, redirect, url_for,
    session, request, jsonify
)
from dotenv import load_dotenv

import bot

load_dotenv()

app = Flask(__name__)
app.secret_key = os.getenv('SECRET_KEY', 'change-this-secret')


# ---------------------------------------------------------------------------
# Auth helpers
# ---------------------------------------------------------------------------
def login_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if not session.get('logged_in'):
            return redirect(url_for('login'))
        return f(*args, **kwargs)
    return decorated


# ---------------------------------------------------------------------------
# Auth routes
# ---------------------------------------------------------------------------
@app.route('/')
def index():
    return redirect(url_for('dashboard'))


@app.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    if request.method == 'POST':
        username = request.form.get('username', '').strip()
        password = request.form.get('password', '')
        if (username == os.getenv('DASHBOARD_USERNAME') and
                password == os.getenv('DASHBOARD_PASSWORD')):
            session['logged_in'] = True
            return redirect(url_for('dashboard'))
        error = 'Invalid username or password.'
    return render_template('login.html', error=error)


@app.route('/logout')
def logout():
    session.clear()
    return redirect(url_for('login'))


# ---------------------------------------------------------------------------
# Dashboard
# ---------------------------------------------------------------------------
@app.route('/dashboard')
@login_required
def dashboard():
    paper = os.getenv('PAPER_TRADING', 'true').lower() == 'true'
    return render_template('dashboard.html', paper=paper)


# ---------------------------------------------------------------------------
# API — bot control
# ---------------------------------------------------------------------------
@app.route('/api/bot/start', methods=['POST'])
@login_required
def api_bot_start():
    started = bot.start_bot()
    return jsonify({'started': started, 'running': bot.bot_state['running']})


@app.route('/api/bot/stop', methods=['POST'])
@login_required
def api_bot_stop():
    stopped = bot.stop_bot()
    return jsonify({'stopped': stopped, 'running': bot.bot_state['running']})


# ---------------------------------------------------------------------------
# API — status & account
# ---------------------------------------------------------------------------
@app.route('/api/status')
@login_required
def api_status():
    try:
        api    = bot.get_api()
        acct   = api.get_account()
        clock  = api.get_clock()
        return jsonify({
            'running':       bot.bot_state['running'],
            'market_open':   clock.is_open,
            'next_open':     clock.next_open.isoformat() if not clock.is_open else None,
            'equity':        float(acct.equity),
            'buying_power':  float(acct.buying_power),
            'cash':          float(acct.cash),
            'last_scan':     bot.bot_state['last_scan'],
            'scan_count':    bot.bot_state['scan_count'],
            'paper_trading': os.getenv('PAPER_TRADING', 'true').lower() == 'true',
        })
    except Exception as e:
        return jsonify({'error': str(e)}), 500


# ---------------------------------------------------------------------------
# API — positions
# ---------------------------------------------------------------------------
@app.route('/api/positions')
@login_required
def api_positions():
    try:
        api       = bot.get_api()
        positions = api.list_positions()
        return jsonify([
            {
                'symbol':          p.symbol,
                'qty':             p.qty,
                'avg_entry_price': float(p.avg_entry_price),
                'current_price':   float(p.current_price),
                'market_value':    float(p.market_value),
                'unrealized_pl':   float(p.unrealized_pl),
                'unrealized_plpc': float(p.unrealized_plpc),
                'side':            p.side,
            }
            for p in positions
        ])
    except Exception as e:
        return jsonify({'error': str(e)}), 500


# ---------------------------------------------------------------------------
# API — trade log
# ---------------------------------------------------------------------------
@app.route('/api/log')
@login_required
def api_log():
    limit = request.args.get('limit', 100, type=int)
    return jsonify(bot.bot_state['trade_log'][:limit])


# ---------------------------------------------------------------------------
# API — watchlist
# ---------------------------------------------------------------------------
@app.route('/api/watchlist', methods=['GET', 'POST'])
@login_required
def api_watchlist():
    if request.method == 'POST':
        data = request.get_json(silent=True) or {}
        raw  = data.get('watchlist', [])
        bot.bot_state['watchlist'] = [s.strip().upper() for s in raw if s.strip()]
        bot.log_event(f'Watchlist updated: {", ".join(bot.bot_state["watchlist"])}')
    return jsonify({'watchlist': bot.bot_state['watchlist']})


# ---------------------------------------------------------------------------
# Entry point (dev only — use gunicorn in production)
# ---------------------------------------------------------------------------
if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)
