package com.goldenchart.controller;

import com.goldenchart.dto.IndicatorRequest;
import com.goldenchart.dto.IndicatorResponse;
import com.goldenchart.service.IndicatorService;
import com.goldenchart.service.IndicatorSettingsService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

/**
 * 지표 계산 REST API.
 *
 * <p>파라미터 우선순위 (높은 순):
 * <ol>
 *   <li>요청 body 의 params (프론트엔드가 명시적으로 보낸 값)</li>
 *   <li>DB gc_indicator_settings 에 저장된 사용자 설정값</li>
 *   <li>IndicatorService 내부 코드 기본값 (최후 fallback)</li>
 * </ol>
 * 이 순서로 병합하여 프론트엔드와 백엔드가 항상 동일한 파라미터로 계산된다.
 * </p>
 */
@RestController
@RequestMapping("/indicators")
@RequiredArgsConstructor
public class IndicatorController {

    private final IndicatorService indicatorService;
    private final IndicatorSettingsService settingsService;

    /**
     * 지표값 계산.
     *
     * <p>헤더:
     * <ul>
     *   <li>X-Device-Id — 비회원 기기 식별자</li>
     *   <li>X-User-Id   — 회원 ID (선택)</li>
     * </ul>
     */
    @PostMapping("/calculate")
    public ResponseEntity<IndicatorResponse> calculate(
            @RequestBody IndicatorRequest req,
            @RequestHeader(value = "X-User-Id",   required = false) String userIdHeader,
            @RequestHeader(value = "X-Device-Id", required = false) String deviceId) {

        if (req.getBars() == null || req.getBars().isEmpty()) {
            return ResponseEntity.badRequest().build();
        }

        Long userId = parseUserId(userIdHeader);

        /*
         * DB 설정값 + 요청 파라미터 병합.
         * - DB 값 기반으로 시작
         * - 요청 params 는 DB 값 위에 덮어쓰기 (명시적 전송이 더 최신)
         */
        Map<String, Object> mergedParams = settingsService.mergeWithDb(
                userId, deviceId,
                req.getParams(),
                req.getIndicatorType());

        IndicatorResponse response = indicatorService.calculate(
                req.getBars(), req.getIndicatorType(), mergedParams, req.getTimeframe());
        response.setSymbol(req.getSymbol());
        response.setTimeframe(req.getTimeframe());
        return ResponseEntity.ok(response);
    }

    /**
     * 지원 지표 목록 반환.
     * frontend indicatorRegistry.ts 의 INDICATOR_REGISTRY 와 동기화.
     */
    @GetMapping("/list")
    public ResponseEntity<?> list() {
        return ResponseEntity.ok(java.util.Map.of(
            "supported", java.util.List.of(
                "SMA", "EMA", "WMA", "HMA", "VWMA", "DEMA", "TEMA", "RMA", "SMMA", "LSMA", "MACross",
                "BollingerBands", "KeltnerChannels", "DonchianChannels", "BBPercentB", "BBBandWidth",
                "RSI", "Stochastic", "StochRSI", "CCI", "WilliamsPercentRange",
                "AwesomeOscillator", "DPO",
                "MACD", "Momentum", "ROC", "TSI",
                "ADX", "DMI", "Aroon", "IchimokuCloud", "ParabolicSAR",
                "Choppiness", "MassIndex",
                "ATR", "StandardDeviation", "HistoricalVolatility",
                "OBV", "MFI", "ChaikinMF",
                "VolumeOscillator", "VR", "Disparity",
                "Psychological", "InvestPsychological",
                "TRIX", "ADX", "DMI"
            )
        ));
    }

    // ── helpers ───────────────────────────────────────────────────────────────

    private Long parseUserId(String header) {
        if (header == null || header.isBlank()) return null;
        try { return Long.parseLong(header); } catch (NumberFormatException e) { return null; }
    }
}
