package services

import (
	"encoding/json"
	"fmt"
	"stocksearch/models"
	"strings"
	"time"
)

// ThemeService 테마 분석 서비스
type ThemeService struct {
	kiwoom *KiwoomClient
	cache  *CacheService
}

var themeSvc *ThemeService

// GetThemeService 테마 서비스 싱글턴 반환
func GetThemeService() *ThemeService {
	if themeSvc == nil {
		themeSvc = &ThemeService{
			kiwoom: GetKiwoomClient(),
			cache:  GetCacheService(),
		}
	}
	return themeSvc
}

// GetThemes ka90001: 테마그룹 목록 조회 (캐시 1분)
// sortTp: "3"=상위등락률, "1"=상위기간수익률
func (s *ThemeService) GetThemes(dateTp, sortTp string) ([]models.ThemeGroup, error) {
	cacheKey := fmt.Sprintf("themes:%s:%s", dateTp, sortTp)
	if cached, ok := s.cache.Get(cacheKey); ok {
		if groups, ok := cached.([]models.ThemeGroup); ok {
			return groups, nil
		}
	}

	body, err := s.kiwoom.post("ka90001", "/api/dostk/thme", map[string]string{
		"qry_tp":        "0", // 전체검색
		"stk_cd":        "",
		"date_tp":       dateTp,
		"thema_nm":      "",
		"flu_pl_amt_tp": sortTp,
		"stex_tp":       "1", // KRX
	})
	if err != nil {
		return nil, fmt.Errorf("테마 목록 조회 실패: %w", err)
	}

	var result struct {
		ThemaGrp []struct {
			ThemaGrpCd   string `json:"thema_grp_cd"`
			ThemaNm      string `json:"thema_nm"`
			StkNum       string `json:"stk_num"`
			FluSig       string `json:"flu_sig"`
			FluRt        string `json:"flu_rt"`
			RisingStkNum string `json:"rising_stk_num"`
			FallStkNum   string `json:"fall_stk_num"`
			DtPrftRt     string `json:"dt_prft_rt"`
			MainStk      string `json:"main_stk"`
		} `json:"thema_grp"`
		ReturnCode int    `json:"return_code"`
		ReturnMsg  string `json:"return_msg"`
	}
	if err := json.Unmarshal(body, &result); err != nil {
		return nil, fmt.Errorf("테마 목록 파싱 실패: %w", err)
	}
	if result.ReturnCode != 0 {
		return nil, fmt.Errorf("테마 목록 조회 실패: %s", result.ReturnMsg)
	}

	groups := make([]models.ThemeGroup, 0, len(result.ThemaGrp))
	for _, g := range result.ThemaGrp {
		groups = append(groups, models.ThemeGroup{
			Code:        g.ThemaGrpCd,
			Name:        g.ThemaNm,
			StockCount:  int(parseIntSafe(g.StkNum)),
			FluSig:      g.FluSig,
			FluRt:       parseFloatSafe(strings.TrimPrefix(g.FluRt, "+")),
			RisingCount: int(parseIntSafe(g.RisingStkNum)),
			FallCount:   int(parseIntSafe(g.FallStkNum)),
			PeriodRt:    parseFloatSafe(strings.TrimPrefix(g.DtPrftRt, "+")),
			MainStock:   g.MainStk,
		})
	}

	s.cache.Set(cacheKey, groups, time.Minute)
	return groups, nil
}

// GetThemeStocks ka90002: 테마구성종목 조회 (캐시 2분)
func (s *ThemeService) GetThemeStocks(themeCode, dateTp string) (*models.ThemeDetail, error) {
	cacheKey := fmt.Sprintf("theme_stocks:%s:%s", themeCode, dateTp)
	if cached, ok := s.cache.Get(cacheKey); ok {
		if detail, ok := cached.(*models.ThemeDetail); ok {
			return detail, nil
		}
	}

	body, err := s.kiwoom.post("ka90002", "/api/dostk/thme", map[string]string{
		"thema_grp_cd": themeCode,
		"date_tp":      dateTp,
		"stex_tp":      "1", // KRX
	})
	if err != nil {
		return nil, fmt.Errorf("테마 구성종목 조회 실패: %w", err)
	}

	var result struct {
		FluRt      string `json:"flu_rt"`
		DtPrftRt   string `json:"dt_prft_rt"`
		ThemaCompStk []struct {
			StkCd   string `json:"stk_cd"`
			StkNm   string `json:"stk_nm"`
			CurPrc  string `json:"cur_prc"`
			FluSig  string `json:"flu_sig"`
			PredPre string `json:"pred_pre"`
			FluRt   string `json:"flu_rt"`
		} `json:"thema_comp_stk"`
		ReturnCode int    `json:"return_code"`
		ReturnMsg  string `json:"return_msg"`
	}
	if err := json.Unmarshal(body, &result); err != nil {
		return nil, fmt.Errorf("테마 구성종목 파싱 실패: %w", err)
	}
	if result.ReturnCode != 0 {
		return nil, fmt.Errorf("테마 구성종목 조회 실패: %s", result.ReturnMsg)
	}

	stocks := make([]models.ThemeStock, 0, len(result.ThemaCompStk))
	for _, s := range result.ThemaCompStk {
		stocks = append(stocks, models.ThemeStock{
			Code:    s.StkCd,
			Name:    s.StkNm,
			CurPrc:  absParseIntSafe(s.CurPrc),
			FluSig:  s.FluSig,
			PredPre: parseIntSafe(s.PredPre),
			FluRt:   parseFloatSafe(strings.TrimPrefix(s.FluRt, "+")),
		})
	}

	detail := &models.ThemeDetail{
		FluRt:    parseFloatSafe(strings.TrimPrefix(result.FluRt, "+")),
		PeriodRt: parseFloatSafe(strings.TrimPrefix(result.DtPrftRt, "+")),
		Stocks:   stocks,
	}

	s.cache.Set(cacheKey, detail, 2*time.Minute)
	return detail, nil
}
