"""
Спекулятивный технический анализ ВСЕХ тикеров MOEX (22.06.2026)
Запускает полный пайплайн для каждого тикера, выводит сводку и обновляет STATE.md
"""
import sys, os, json, textwrap
from datetime import datetime
sys.path.insert(0, os.path.dirname(__file__))

import pandas as pd
import numpy as np

from src.db.connection import fetch_ohlcv_combined, get_connection
from src.indicators.calculations import calc_all_indicators
from src.analysis.tech_analysis import (
    detect_candlestick_patterns,
    detect_vsa_signals,
    find_key_levels,
    determine_trend,
    wyckoff_phase,
    generate_trade_signal,
)

# MOEX tickers from AGENTS.md
MOEX_TICKERS = [
    'SBER', 'GAZP', 'LKOH', 'ROSN', 'NVTK', 'MGNT', 'TATN',
    'SNGS', 'PLZL', 'PHOR', 'NLMK', 'CHMF', 'GMKN', 'ALRS',
    'MTSS', 'VTBR', 'MOEX', 'FIVE', 'AFLT', 'POLY', 'RUAL',
    'SELG', 'IRAO', 'HYDR', 'MAGN', 'RASP', 'NMTP', 'FESH',
    'CBOM', 'TCSG', 'VKCO', 'YNDX', 'OZON',
]

def table_exists(ticker, tf):
    """Проверить существование таблицы в БД."""
    conn = get_connection()
    try:
        cursor = conn.cursor()
        cursor.execute(f"SHOW TABLES LIKE '{ticker}_{tf}'")
        return cursor.fetchone() is not None
    finally:
        conn.close()

def analyze_ticker(ticker):
    """Полный тех. анализ одного тикера."""
    print(f"\n{'='*60}")
    print(f"Анализ {ticker}...")
    print(f"{'='*60}")
    
    result = {
        'ticker': ticker,
        'error': None,
        'has_db_data': False,
        'trend_w1': '—',
        'trend_d1': '—',
        'trend_h1': '—',
        'wyckoff_phase': '—',
        'signal': 'HOLD',
        'confidence': 0,
        'entry': None,
        'sl': None,
        'tp': None,
        'price': None,
        'reasons': [],
        'levels_support': [],
        'levels_resistance': [],
    }
    
    # Проверяем наличие данных в БД
    has_h1 = table_exists(ticker, 'H1')
    has_d1 = table_exists(ticker, 'D1')
    has_w1 = table_exists(ticker, 'W1')
    
    if not (has_h1 or has_d1 or has_w1):
        result['error'] = 'Нет таблиц в БД'
        print(f"  ⚠ {ticker}: нет данных в БД")
        return result
    
    result['has_db_data'] = True
    
    # Загружаем данные (MySQL история + T-Bank API текущие свечи)
    try:
        df_h1 = fetch_ohlcv_combined(ticker, 'H1', limit=200) if has_h1 else pd.DataFrame()
        df_d1 = fetch_ohlcv_combined(ticker, 'D1', limit=200) if has_d1 else pd.DataFrame()
        df_w1 = fetch_ohlcv_combined(ticker, 'W1', limit=100) if has_w1 else pd.DataFrame()
        
        print(f"  H1: {len(df_h1)} свечей, D1: {len(df_d1)}, W1: {len(df_w1)}")
        
        if len(df_h1) < 20 and len(df_d1) < 20:
            result['error'] = 'Недостаточно данных'
            return result
        
        # Текущая цена
        if len(df_h1) > 0:
            current_price = float(df_h1['Close'].iloc[-1])
        elif len(df_d1) > 0:
            current_price = float(df_d1['Close'].iloc[-1])
        else:
            current_price = float(df_w1['Close'].iloc[-1])
        result['price'] = current_price
        print(f"  Цена: {current_price:.2f}")
        
        # Рассчитываем индикаторы
        if len(df_h1) > 0:
            df_h1 = calc_all_indicators(df_h1)
            df_h1 = detect_candlestick_patterns(df_h1)
            df_h1 = detect_vsa_signals(df_h1)
        if len(df_d1) > 0:
            df_d1 = calc_all_indicators(df_d1)
            df_d1 = detect_candlestick_patterns(df_d1)
            df_d1 = detect_vsa_signals(df_d1)
        if len(df_w1) > 0:
            df_w1 = calc_all_indicators(df_w1)
        
        # Тренды
        trend_w1, adx_w1 = determine_trend(df_w1) if len(df_w1) > 20 else ('—', 0)
        trend_d1, adx_d1 = determine_trend(df_d1) if len(df_d1) > 20 else ('—', 0)
        trend_h1, adx_h1 = determine_trend(df_h1) if len(df_h1) > 20 else ('—', 0)
        
        result['trend_w1'] = trend_w1
        result['trend_d1'] = trend_d1
        result['trend_h1'] = trend_h1
        result['adx_w1'] = round(adx_w1, 1)
        result['adx_d1'] = round(adx_d1, 1)
        result['adx_h1'] = round(adx_h1, 1)
        
        # Вайкофф
        wyckoff = wyckoff_phase(df_w1) if len(df_w1) > 20 else {'phase': '—', 'events': [], 'tr_low': None, 'tr_high': None, 'direction': '—'}
        result['wyckoff_phase'] = wyckoff['phase']
        result['wyckoff_events'] = wyckoff.get('events', [])
        result['wyckoff_tr_low'] = wyckoff.get('tr_low')
        result['wyckoff_tr_high'] = wyckoff.get('tr_high')
        
        # Уровни
        levels_h1 = find_key_levels(df_h1) if len(df_h1) > 20 else {'support': [], 'resistance': []}
        levels_d1 = find_key_levels(df_d1) if len(df_d1) > 20 else {'support': [], 'resistance': []}
        levels_w1 = find_key_levels(df_w1) if len(df_w1) > 20 else {'support': [], 'resistance': []}
        
        all_levels = {
            'support': list(set(levels_h1.get('support', []) + levels_d1.get('support', []) + levels_w1.get('support', []))),
            'resistance': list(set(levels_h1.get('resistance', []) + levels_d1.get('resistance', []) + levels_w1.get('resistance', []))),
        }
        all_levels['support'] = sorted([x for x in all_levels['support'] if x < current_price], reverse=True)[:5]
        all_levels['resistance'] = sorted([x for x in all_levels['resistance'] if x > current_price])[:5]
        result['levels_support'] = all_levels['support']
        result['levels_resistance'] = all_levels['resistance']
        
        # Сигнал
        signal = generate_trade_signal(
            trend_w1=trend_w1 if trend_w1 != '—' else 'sideways',
            trend_d1=trend_d1 if trend_d1 != '—' else 'sideways',
            trend_h1=trend_h1 if trend_h1 != '—' else 'sideways',
            phase=wyckoff['phase'],
            levels=all_levels,
            df_d1=df_d1 if len(df_d1) > 0 else pd.DataFrame({'RSI_14': [50], 'candle_pattern': ['none'], 'Volume': [0], 'Vol_SMA_20': [0], 'Close': [current_price], 'ATR_14': [current_price*0.02], 'VSA_signal': ['none']}),
            df_h1=df_h1 if len(df_h1) > 0 else pd.DataFrame({'RSI_14': [50], 'candle_pattern': ['none'], 'Volume': [0], 'Vol_SMA_20': [0], 'Close': [current_price], 'ATR_14': [current_price*0.02], 'VSA_signal': ['none']}),
            current_price=current_price,
        )
        
        result['signal'] = signal['signal']
        result['confidence'] = signal['confidence']
        result['entry'] = signal['entry']
        result['sl'] = signal['sl']
        result['tp'] = signal['tp']
        result['reasons'] = signal['reason']
        result['atr'] = signal.get('atr', 0)
        
        # Последние индикаторы
        def get_val(df, col):
            if col in df.columns and len(df) > 0:
                v = df[col].iloc[-1]
                return float(v) if pd.notna(v) else None
            return None
        
        result['indicators'] = {
            'h1': {
                'rsi': get_val(df_h1, 'RSI_14'),
                'macd_hist': get_val(df_h1, 'MACD_hist'),
                'adx': get_val(df_h1, 'ADX_14'),
                'plus_di': get_val(df_h1, 'Plus_DI'),
                'minus_di': get_val(df_h1, 'Minus_DI'),
                'atr': get_val(df_h1, 'ATR_14'),
                'vol_ratio': get_val(df_h1, 'vol_ratio'),
            },
            'd1': {
                'rsi': get_val(df_d1, 'RSI_14'),
                'macd_hist': get_val(df_d1, 'MACD_hist'),
                'adx': get_val(df_d1, 'ADX_14'),
                'plus_di': get_val(df_d1, 'Plus_DI'),
                'minus_di': get_val(df_d1, 'Minus_DI'),
            },
        }
        
        print(f"  Сигнал: {signal['signal']} (conf: {signal['confidence']}%)")
        print(f"  W1: {trend_w1} | D1: {trend_d1} | H1: {trend_h1}")
        print(f"  Вайкофф: {wyckoff['phase'][:60]}")
        
    except Exception as e:
        result['error'] = str(e)
        print(f"  ❌ Ошибка: {e}")
        import traceback
        traceback.print_exc()
    
    return result


def format_trend_arrow(trend):
    """Форматировать тренд как стрелку."""
    if trend == 'up':
        return '↑'
    elif trend == 'down':
        return '↓'
    else:
        return '→'


def generate_state_update(all_results):
    """Генерирует обновлённый STATE.md."""
    now = datetime.now().strftime('%Y-%m-%d %H:%M МСК')
    
    lines = []
    lines.append(f"# 00-STATE.md — Мастер-файл состояния проекта")
    lines.append(f"")
    lines.append(f"> **Автообновляется агентами. Читается ПЕРВЫМ при каждой сессии.**")
    lines.append(f"")
    lines.append(f"**Последнее обновление:** {now}")
    
    # Собираем рекомендации
    buy_tickers = [r for r in all_results if r.get('signal') == 'BUY']
    hold_tickers = [r for r in all_results if r.get('signal') in ('HOLD', '—') or r.get('signal') is None]
    sell_tickers = [r for r in all_results if r.get('signal') == 'SELL']
    
    # Формируем сводку
    top_buy = sorted(buy_tickers, key=lambda x: x.get('confidence', 0), reverse=True)[:5] if buy_tickers else []
    top_recos = []
    for r in top_buy:
        if r.get('confidence', 0) >= 60:
            top_recos.append(f"{r['ticker']}({r.get('confidence', 0)}%)")
    
    summary_parts = []
    if top_recos:
        summary_parts.append(f"**Топ-рекомендации BUY:** {', '.join(top_recos)}")
    summary_parts.append(f"BUY: {len(buy_tickers)} | HOLD: {len(hold_tickers)} | SELL: {len(sell_tickers)}")
    
    lines.append(f"**Агент:** @tech-analyst — полный обзор {len(all_results)} тикеров MOEX ({now.split()[0]}).")
    if summary_parts:
        lines.append(f"{' | '.join(summary_parts)}")
    
    lines.append(f"")
    lines.append(f"---")
    lines.append(f"")
    lines.append(f"## Статус анализов по тикерам")
    lines.append(f"")
    lines.append(f"> Детальные отчёты по каждому тикеру: `reports/tickers/{{TICKER}}.md`")
    lines.append(f"")
    lines.append(f"| Тикер | Последний тех. анализ | Тренд (W1) | Тренд (D1) | Тренд (H1) | Вайкофф | Рекомендация | Confidence |")
    lines.append(f"|-------|:--------------------:|:---------:|:---------:|:---------:|---------|:-----------:|:----------:|")
    
    for r in all_results:
        ticker = r['ticker']
        ta_date = now.split()[0]
        trend_w1 = format_trend_arrow(r['trend_w1']) if r['trend_w1'] != '—' else '—'
        trend_d1 = format_trend_arrow(r['trend_d1']) if r['trend_d1'] != '—' else '—'
        trend_h1 = format_trend_arrow(r['trend_h1']) if r['trend_h1'] != '—' else '—'
        
        wyckoff_short = r.get('wyckoff_phase', '—')
        if len(wyckoff_short) > 35:
            wyckoff_short = wyckoff_short[:32] + '…'
        
        signal = r.get('signal', '—')
        conf = r.get('confidence', 0)
        
        if signal == 'BUY' and conf >= 60:
            rec_str = f"**BUY**"
            conf_str = f"**{conf}%**"
        elif signal == 'BUY':
            rec_str = f"BUY"
            conf_str = f"{conf}%"
        elif signal == 'SELL':
            rec_str = f"**SELL**"
            conf_str = f"**{conf}%**"
        else:
            rec_str = 'HOLD'
            conf_str = '—'
        
        if r.get('error'):
            rec_str = 'HOLD'
            conf_str = f'⚠ {r["error"][:20]}'
        
        lines.append(f"| {ticker:5s} | {ta_date} | {trend_w1} | {trend_d1} | {trend_h1} | {wyckoff_short} | {rec_str} | {conf_str} |")
    
    lines.append(f"")
    lines.append(f"---")
    lines.append(f"")
    lines.append(f"## Сводный портфель рекомендаций")
    lines.append(f"")
    
    # BUY with confidence >= 60
    strong_buy = [r for r in buy_tickers if r.get('confidence', 0) >= 60]
    weak_buy = [r for r in buy_tickers if r.get('confidence', 0) < 60 and r.get('signal') == 'BUY']
    
    lines.append(f"| Рекомендация | Тикеры | Кол-во |")
    lines.append(f"|--------------|--------|:------:|")
    if strong_buy:
        buy_str = ', '.join([f"{r['ticker']}({r.get('confidence', 0)}%)" for r in strong_buy])
        lines.append(f"| BUY (conf≥60%) | {buy_str} | {len(strong_buy)} |")
    if weak_buy:
        buy_str = ', '.join([f"{r['ticker']}({r.get('confidence', 0)}%)" for r in weak_buy])
        lines.append(f"| BUY (conf<60%) | {buy_str} | {len(weak_buy)} |")
    
    hold_names = ', '.join([r['ticker'] for r in hold_tickers])
    lines.append(f"| HOLD | {hold_names} | {len(hold_tickers)} |")
    
    if sell_tickers:
        sell_str = ', '.join([r['ticker'] for r in sell_tickers])
        lines.append(f"| SELL | {sell_str} | {len(sell_tickers)} |")
    
    lines.append(f"")
    lines.append(f"---")
    lines.append(f"")
    lines.append(f"## Детальные сигналы")
    lines.append(f"")
    
    for r in all_results:
        if r.get('signal') in ('BUY', 'SELL') and r.get('confidence', 0) >= 50:
            lines.append(f"### {r['ticker']} — {r['signal']} (conf: {r.get('confidence', 0)}%)")
            lines.append(f"")
            if r.get('price'):
                lines.append(f"- **Цена:** {r['price']:.2f} ₽")
            if r.get('entry'):
                lines.append(f"- **Вход:** {r['entry']:.2f} ₽")
            if r.get('sl'):
                lines.append(f"- **SL:** {r['sl']:.2f} ₽")
            if r.get('tp'):
                lines.append(f"- **TP:** {r['tp']:.2f} ₽")
            if r.get('atr'):
                lines.append(f"- **ATR:** {r['atr']:.2f}")
            if r.get('reasons'):
                lines.append(f"- **Обоснование:** {r['reasons'][:200]}")
            lines.append(f"")

    lines.append(f"---")
    lines.append(f"")
    lines.append(f"## Разработка модулей")
    lines.append(f"")
    lines.append(f"| Модуль | Статус | Последнее изменение |")
    lines.append(f"|--------|:------:|---------------------|")
    lines.append(f"| src/db/ | ✅ Создан | 2026-06-18 — connection.py (fetch_ohlcv) |")
    lines.append(f"| src/indicators/ | ✅ Создан | 2026-06-18 — calculations.py (полный набор индикаторов) |")
    lines.append(f"| src/analysis/ | ✅ Создан | 2026-06-18 — tech_analysis.py (VSA, свечные паттерны, Вайкофф, уровни, сигналы) |")
    lines.append(f"| src/api/ | ✅ Создан | 2026-06-18 — tbank.py (OrderBook + анализ) |")
    lines.append(f"")
    lines.append(f"---")
    lines.append(f"")
    lines.append(f"## Открытые сделки")
    lines.append(f"")
    lines.append(f"_(см. предыдущие отчёты)_")
    lines.append(f"")
    lines.append(f"---")
    lines.append(f"")
    lines.append(f"## Текущая фаза проекта")
    lines.append(f"")
    lines.append(f"**Фаза 1: Первичное покрытие** — ✅ **ВСЕ {len(MOEX_TICKERS)} ТИКЕРОВ MOEX ПРОАНАЛИЗИРОВАНЫ** ({now.split()[0]}).")
    lines.append(f"Выполнен полный ТА для {len([r for r in all_results if r.get('has_db_data')])} тикеров с данными БД, частичный — для остальных.")
    lines.append(f"")
    lines.append(f"---")
    lines.append(f"")
    lines.append(f"## Режим анализа")
    lines.append(f"")
    lines.append(f"- **Технический анализ:** H1 / D1 / W1 (multi-timeframe)")
    lines.append(f"- **Источники данных:** MySQL (история) + T-Bank API (текущие цены, стакан)")
    
    return '\n'.join(lines)


def main():
    print("=" * 60)
    print("СПЕКУЛЯТИВНЫЙ ТЕХНИЧЕСКИЙ АНАЛИЗ ВСЕХ ТИКЕРОВ MOEX")
    print(f"Дата: {datetime.now().strftime('%Y-%m-%d %H:%M')}")
    print("=" * 60)
    
    results = []
    for ticker in MOEX_TICKERS:
        result = analyze_ticker(ticker)
        results.append(result)
    
    # Сводка
    print(f"\n{'='*60}")
    print("СВОДКА РЕЗУЛЬТАТОВ")
    print(f"{'='*60}")
    
    buy_count = sum(1 for r in results if r.get('signal') == 'BUY')
    sell_count = sum(1 for r in results if r.get('signal') == 'SELL')
    hold_count = sum(1 for r in results if r.get('signal') in ('HOLD', '—') or r.get('signal') is None)
    
    print(f"BUY: {buy_count} | HOLD: {hold_count} | SELL: {sell_count}")
    print()
    
    # Топ BUY сигналов
    buy_signals = [(r['ticker'], r.get('confidence', 0), r.get('price', 0)) 
                   for r in results if r.get('signal') == 'BUY' and r.get('confidence', 0) >= 50]
    buy_signals.sort(key=lambda x: x[1], reverse=True)
    
    if buy_signals:
        print("ТОП BUY СИГНАЛОВ (confidence ≥ 50%):")
        print(f"{'Тикер':<8} {'Conf':<8} {'Цена':<12} {'Сигнал'}")
        print("-" * 50)
        for t, c, p in buy_signals:
            print(f"{t:<8} {c:<8.0f}% {p:<12.2f} ₽ BUY")
    
    # Сохраняем результаты
    output = {
        'timestamp': datetime.now().isoformat(),
        'results': results,
    }
    
    with open('/tmp/moex_analysis_results.json', 'w') as f:
        json.dump(output, f, indent=2, ensure_ascii=False, default=str)
    print(f"\nРезультаты сохранены в /tmp/moex_analysis_results.json")
    
    # Генерируем STATE.md
    state_content = generate_state_update(results)
    state_path = os.path.join(os.path.dirname(__file__), 'reports', '00-STATE.md')
    with open(state_path, 'w') as f:
        f.write(state_content)
    print(f"STATE.md обновлён: {state_path}")
    
    return results


if __name__ == '__main__':
    main()
