package services

import (
	"encoding/json"
	"fmt"
)

// OrderService 주식 주문 서비스 (매수/매도/정정/취소)
type OrderService struct {
	client *KiwoomClient
}

var orderService *OrderService

// GetOrderService 주문 서비스 싱글턴 반환
func GetOrderService() *OrderService {
	if orderService == nil {
		orderService = &OrderService{client: GetKiwoomClient()}
	}
	return orderService
}

// OrderRequest 주문 요청 파라미터
type OrderRequest struct {
	Exchange string // KRX, NXT, SOR
	Code     string // 종목코드
	Qty      string // 주문수량
	Price    string // 주문단가 (시장가 시 빈 문자열)
	TradeTP  string // 0:보통, 3:시장가, 5:조건부지정가, 6:최유리, 7:최우선
}

// OrderResult 주문 응답
type OrderResult struct {
	OrderNo    string `json:"orderNo"`
	ReturnCode int    `json:"returnCode"`
	ReturnMsg  string `json:"returnMsg"`
}

// Buy 매수주문 (kt10000)
func (s *OrderService) Buy(req OrderRequest) (*OrderResult, error) {
	body := map[string]string{
		"dmst_stex_tp": req.Exchange,
		"stk_cd":       req.Code,
		"ord_qty":      req.Qty,
		"ord_uv":       req.Price,
		"trde_tp":      req.TradeTP,
		"cond_uv":      "",
	}

	respBody, err := s.client.post("kt10000", "/api/dostk/ordr", body)
	if err != nil {
		return nil, fmt.Errorf("매수주문 실패: %w", err)
	}

	return parseOrderResult(respBody)
}

// Sell 매도주문 (kt10001)
func (s *OrderService) Sell(req OrderRequest) (*OrderResult, error) {
	body := map[string]string{
		"dmst_stex_tp": req.Exchange,
		"stk_cd":       req.Code,
		"ord_qty":      req.Qty,
		"ord_uv":       req.Price,
		"trde_tp":      req.TradeTP,
		"cond_uv":      "",
	}

	respBody, err := s.client.post("kt10001", "/api/dostk/ordr", body)
	if err != nil {
		return nil, fmt.Errorf("매도주문 실패: %w", err)
	}

	return parseOrderResult(respBody)
}

// Modify 정정주문 (kt10002)
func (s *OrderService) Modify(exchange, origOrdNo, code, qty, price string) (*OrderResult, error) {
	body := map[string]string{
		"dmst_stex_tp": exchange,
		"orig_ord_no":  origOrdNo,
		"stk_cd":       code,
		"mdfy_qty":     qty,
		"mdfy_uv":      price,
		"mdfy_cond_uv": "",
	}

	respBody, err := s.client.post("kt10002", "/api/dostk/ordr", body)
	if err != nil {
		return nil, fmt.Errorf("정정주문 실패: %w", err)
	}

	return parseOrderResult(respBody)
}

// Cancel 취소주문 (kt10003)
// qty: "0" = 전량취소
func (s *OrderService) Cancel(exchange, origOrdNo, code, qty string) (*OrderResult, error) {
	body := map[string]string{
		"dmst_stex_tp": exchange,
		"orig_ord_no":  origOrdNo,
		"stk_cd":       code,
		"cncl_qty":     qty,
	}

	respBody, err := s.client.post("kt10003", "/api/dostk/ordr", body)
	if err != nil {
		return nil, fmt.Errorf("취소주문 실패: %w", err)
	}

	return parseOrderResult(respBody)
}

// parseOrderResult 주문 응답 JSON 파싱 공통 함수
func parseOrderResult(body []byte) (*OrderResult, error) {
	var result struct {
		OrdNo      string `json:"ord_no"`
		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)
	}
	return &OrderResult{
		OrderNo:    result.OrdNo,
		ReturnCode: result.ReturnCode,
		ReturnMsg:  result.ReturnMsg,
	}, nil
}
