package services

import (
	"fmt"
	"stocksearch/models"
	"time"
)

// StockService 주식 비즈니스 로직 (캐시 + 키움 API 조합)
type StockService struct {
	kiwoom *KiwoomClient
	cache  *CacheService
}

var stockSvc *StockService

// GetStockService 주식 서비스 싱글턴 반환
func GetStockService() *StockService {
	if stockSvc == nil {
		stockSvc = &StockService{
			kiwoom: GetKiwoomClient(),
			cache:  GetCacheService(),
		}
	}
	return stockSvc
}

// GetCurrentPrice 현재가 조회 (1초 캐시 적용)
func (s *StockService) GetCurrentPrice(stockCode string) (*models.StockPrice, error) {
	cacheKey := "price:" + stockCode
	if cached, ok := s.cache.Get(cacheKey); ok {
		if price, ok := cached.(*models.StockPrice); ok {
			return price, nil
		}
	}

	price, err := s.kiwoom.GetCurrentPrice(stockCode)
	if err != nil {
		return nil, fmt.Errorf("현재가 조회 실패 [%s]: %w", stockCode, err)
	}

	s.cache.Set(cacheKey, price, 30*time.Second)
	return price, nil
}

// GetDailyChart 일봉 데이터 조회 (5분 캐시 적용)
func (s *StockService) GetDailyChart(stockCode string) ([]models.CandleData, error) {
	cacheKey := "chart:daily:" + stockCode
	if cached, ok := s.cache.Get(cacheKey); ok {
		if candles, ok := cached.([]models.CandleData); ok {
			return candles, nil
		}
	}

	candles, err := s.kiwoom.GetDailyChart(stockCode)
	if err != nil {
		return nil, fmt.Errorf("일봉 조회 실패 [%s]: %w", stockCode, err)
	}

	s.cache.Set(cacheKey, candles, 5*time.Minute)
	return candles, nil
}

// GetMinuteChart 분봉 데이터 조회 (30초 캐시 적용)
func (s *StockService) GetMinuteChart(stockCode string, minutes int) ([]models.CandleData, error) {
	cacheKey := fmt.Sprintf("chart:minute%d:%s", minutes, stockCode)
	if cached, ok := s.cache.Get(cacheKey); ok {
		if candles, ok := cached.([]models.CandleData); ok {
			return candles, nil
		}
	}

	candles, err := s.kiwoom.GetMinuteChart(stockCode, minutes)
	if err != nil {
		return nil, fmt.Errorf("분봉 조회 실패 [%s]: %w", stockCode, err)
	}

	s.cache.Set(cacheKey, candles, 30*time.Second)
	return candles, nil
}

// GetTopFluctuation 상위 등락률 종목 조회 (1분 캐시 적용)
func (s *StockService) GetTopFluctuation(market string, ascending bool, count int) ([]models.StockPrice, error) {
	dir := "up"
	if ascending {
		dir = "down"
	}
	cacheKey := fmt.Sprintf("fluctuation:%s:%s:%d", market, dir, count)

	if cached, ok := s.cache.Get(cacheKey); ok {
		if stocks, ok := cached.([]models.StockPrice); ok {
			return stocks, nil
		}
	}

	stocks, err := s.kiwoom.GetTopFluctuation(market, ascending, count)
	if err != nil {
		return nil, fmt.Errorf("등락률 조회 실패: %w", err)
	}

	s.cache.Set(cacheKey, stocks, 1*time.Minute)
	return stocks, nil
}
