package service

import TradingDecision
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import model.CandleData
import network.KisTradeService
import network.NewsService
import java.time.LocalTime
import kotlin.collections.List

// service/AutoTradingManager.kt
object AutoTradingManager {
    private val scope = CoroutineScope(Dispatchers.Default)
    val targetStocks = mutableListOf<String>()

    fun addStock(stockCode : String, result :(String, Boolean)->Unit) {
        targetStocks.add(stockCode)
        startTradingLoop(result)
    }

    fun startTradingLoop(result :(String, Boolean)->Unit) {
        scope.launch {
            println("🚀 10분 주기 자동 분석 및 매매 시작: ${LocalTime.now()}")
            targetStocks.forEach { stockCode ->
                launch { // 종목별 병렬 분석 (M3 Pro 파워 활용)
                    RagService.processStock(stockCode,result) {code ,decision ->
                        when (decision?.decision) {
                            "BUY" -> if (decision.confidence > 70) executeOrder(stockCode, "매수")
                            "SELL" -> executeOrder(stockCode, "매도")
                            else -> println("[$stockCode] 관망 유지: ${decision?.reason}")
                        }
                        result(decision.toString(),true)
                    }
                }
            }
            delay(10 * 60 * 1000) // 10분 대기
        }
    }



    private fun executeOrder(code: String, type: String) {
        // 실제 증권사 API 호출 로직 (한국투자증권, 키움 등)
        println("🔥 [주문 집행] $code $type 완료")
    }
}

object TechnicalAnalyzer {
    var monthly: List<CandleData> = emptyList()
    var weekly: List<CandleData> = emptyList()
    var daily: List<CandleData> = emptyList()
    var min30: List<CandleData> = emptyList()

    
    fun generateComprehensiveReport(): String {
        // [1] 단기 에너지 지표 계산 (최근 30분봉 기준)
        val obv = calculateOBV(min30)
        val mfi = calculateMFI(min30, 14)
        val adLine = calculateADLine(min30)

        // [2] 시계열별 가격 변동 및 추세 요약
        val m10 = min30.takeLast(10)
        val change10 = calculateChange(m10)
        val change30 = calculateChange(min30)
        val changeDaily = calculateChange(daily.takeLast(2)) // 전일 대비

        // [3] 이평선 및 가격 위치
        val ma5 = m10.takeLast(5).map { it.stck_prpr.toDouble() }.average()
        val currentPrice = min30.last().stck_prpr.toDouble()

        // [4] 거래량 강도
        val avgVol30 = min30.map { it.cntg_vol.toLong() }.average()
        val recentVol5 = m10.takeLast(5).map { it.cntg_vol.toLong() }.average()
        val volStrength = if (avgVol30 > 0) recentVol5 / avgVol30 else 1.0

        return """
            [종합 시계열 및 에너지 분석 보고서]
            
            1. 가격 및 추세 현황
            - 월봉/주봉 위치: ${if(calculateChange(monthly) > 0) "장기 상승" else "장기 하락"} / ${if(calculateChange(weekly) > 0) "중기 상승" else "중기 하락"}
            - 일봉 대비: ${ "%.2f".format(changeDaily) }% 변동
            - 30분 대비: ${ "%.2f".format(change30) }% 변동
            - 10분 대비: ${ "%.2f".format(change10) }% 변동
            - 이평선 상태: 현재가(${currentPrice.toInt()}) vs MA5(${ma5.toInt()}) -> ${if(currentPrice > ma5) "상단 위치" else "하단 위치"}
            
            2. 자금 흐름 및 에너지 지표
            - OBV (누적 거래량 에너지): ${ "%.0f".format(obv) } (${if(obv > 0) "누적 매수 우위" else "누적 매도 우위"})
            - MFI (자금 유입 지수): ${ "%.1f".format(mfi) } (과매수 기준: 80 / 과매도 기준: 20)
            - A/D (누적 분산 라인): ${ "%.0f".format(adLine) } (종가 형성 위치와 거래량 결합 수치)
            - 거래량 강도: 최근 5분 평균이 30분 평균의 ${ "%.1f".format(volStrength) }배 수준
            
            3. 가격 변동 범위
            - 30분봉 최고가: ${min30.maxOf { it.stck_hgpr.toInt() }}
            - 30분봉 최저가: ${min30.minOf { it.stck_lwpr.toInt() }}
            - RSI(14): ${ "%.1f".format(calculateRSI(min30)) }
        """.trimIndent()
    }

    private fun calculateChange(list: List<CandleData>): Double {
        val start = list.first().stck_oprc.toDouble()
        val end = list.last().stck_prpr.toDouble()
        return if (start != 0.0) ((end - start) / start) * 100 else 0.0
    }

    private fun calculateRSI(list: List<CandleData>): Double {
        if (list.size < 2) return 50.0
        var gains = 0.0
        var losses = 0.0
        for (i in 1 until list.size) {
            val diff = list[i].stck_prpr.toDouble() - list[i - 1].stck_prpr.toDouble()
            if (diff > 0) gains += diff else losses -= diff
        }
        return if (gains + losses == 0.0) 50.0 else (gains / (gains + losses)) * 100
    }

    fun calculateOBV(candles: List<CandleData>): Double {
        var obv = 0.0
        for (i in 1 until candles.size) {
            val prevClose = candles[i - 1].stck_prpr.toDouble()
            val currClose = candles[i].stck_prpr.toDouble()
            val currVol = candles[i].cntg_vol.toDouble()

            when {
                currClose > prevClose -> obv += currVol
                currClose < prevClose -> obv -= currVol
            }
        }
        return obv
    }

    /**
     * MFI (Money Flow Index) 계산 (기간: 보통 14일)
     */
    fun calculateMFI(candles: List<CandleData>, period: Int = 14): Double {
        val subList = candles.takeLast(period + 1)
        var posFlow = 0.0
        var negFlow = 0.0

        for (i in 1 until subList.size) {
            val prevTypical = (subList[i-1].stck_hgpr.toDouble() + subList[i-1].stck_lwpr.toDouble() + subList[i-1].stck_prpr.toDouble()) / 3
            val currTypical = (subList[i].stck_hgpr.toDouble() + subList[i].stck_lwpr.toDouble() + subList[i].stck_prpr.toDouble()) / 3
            val moneyFlow = currTypical * subList[i].cntg_vol.toDouble()

            if (currTypical > prevTypical) posFlow += moneyFlow
            else if (currTypical < prevTypical) negFlow += moneyFlow
        }

        return if (negFlow == 0.0) 100.0 else 100 - (100 / (1+ (posFlow / negFlow)))
    }

    private fun calculateADLine(candles: List<CandleData>): Double {
        var ad = 0.0
        candles.forEach {
            val high = it.stck_hgpr.toDouble(); val low = it.stck_lwpr.toDouble(); val close = it.stck_prpr.toDouble()
            val mfv = if (high != low) ((close - low) - (high - close)) / (high - low) else 0.0
            ad += mfv * it.cntg_vol.toDouble()
        }
        return ad
    }

    fun clear() {
        monthly  = emptyList()
        weekly = emptyList()
        daily = emptyList()
        min30 = emptyList()
    }

}