/**
 * useIndicatorSettings
 *
 * 전역 지표 파라미터 및 시각 설정(색상·선굵기·수평선)을 DB와 동기화하는 훅.
 *
 * - 앱 시작 시 DB에서 로드 → indicatorRegistry.ts 하드코딩 기본값을 완전 대체
 * - 지표 파라미터 또는 시각 설정이 변경되면 DB에 저장
 * - 백엔드 Ta4j 계산 시에도 동일한 파라미터 값 사용
 *
 * 사용 예:
 * ```tsx
 * const { getParams, saveParams, getVisualConfig, saveVisual } = useIndicatorSettings();
 *
 * // 지표 추가 시: DB 저장값 우선 적용 (파라미터 + 색상)
 * const params = getParams(type, def.defaultParams);
 * const { plots, hlines } = getVisualConfig(type, def.plots, def.hlines);
 *
 * // 지표 설정 저장 시: 파라미터 + 시각 설정 모두 DB에 반영
 * saveParams(updated.type, updated.params);
 * saveVisual(updated.type, updated.plots, updated.hlines);
 * ```
 */

import { useEffect, useRef, useCallback } from 'react';
import { getIndicatorDef, mergePlotDefs, normalizeHLines, PlotDef, HLineDef } from '../utils/indicatorRegistry';
import { createDefaultSmaParams, createDefaultSmaPlots, normalizeSmaConfig } from '../utils/smaConfig';
import { normalizeIchimokuConfig, mergeIchimokuPlots } from '../utils/ichimokuConfig';
import {
  DEFAULT_ICHIMOKU_CLOUD_COLORS,
  type IchimokuCloudColors,
  resolveIchimokuCloudColors,
} from '../utils/ichimokuConfig';
import {
  loadIndicatorSettings,
  saveIndicatorSettings,
  saveAllIndicatorSettings,
  loadIndicatorVisualSettings,
  saveIndicatorVisualSettings,
} from '../utils/backendApi';

type ParamMap = Record<string, unknown>;
type AllSettings = Record<string, ParamMap>;

export interface IndicatorVisual {
  plots?:  PlotDef[];
  hlines?: HLineDef[];
  cloudColors?: IchimokuCloudColors;
}
type VisualCache = Record<string, IndicatorVisual>;

// ── 전역 싱글톤 캐시 — 여러 슬롯에서 공유하여 중복 네트워크 요청 방지 ──
let _cache: AllSettings | null = null;
let _loadPromise: Promise<AllSettings> | null = null;

let _visualCache: VisualCache | null = null;
let _visualLoadPromise: Promise<VisualCache> | null = null;

function ensureLoaded(): Promise<AllSettings> {
  if (_cache !== null) return Promise.resolve(_cache);
  if (_loadPromise) return _loadPromise;
  _loadPromise = loadIndicatorSettings().then(data => {
    _cache = (data as AllSettings) ?? {};
    _loadPromise = null;
    return _cache;
  });
  return _loadPromise;
}

function ensureVisualLoaded(): Promise<VisualCache> {
  if (_visualCache !== null) return Promise.resolve(_visualCache);
  if (_visualLoadPromise) return _visualLoadPromise;
  _visualLoadPromise = loadIndicatorVisualSettings().then(data => {
    _visualCache = (data as VisualCache) ?? {};
    _visualLoadPromise = null;
    return _visualCache;
  });
  return _visualLoadPromise;
}

/** 캐시를 강제로 무효화 (테스트 또는 로그아웃 시) */
export function invalidateIndicatorSettingsCache() {
  _cache = null;
  _loadPromise = null;
  _visualCache = null;
  _visualLoadPromise = null;
}

// ─────────────────────────────────────────────────────────────────────────────

export function useIndicatorSettings(sessionKey = 0) {
  // 로그인/로그아웃 시 지표 설정 재로드
  useEffect(() => {
    invalidateIndicatorSettingsCache();
    ensureLoaded().catch(err =>
      console.error('[useIndicatorSettings] params load failed', err)
    );
    ensureVisualLoaded().catch(err =>
      console.error('[useIndicatorSettings] visual load failed', err)
    );
  }, [sessionKey]);

  // ── 파라미터 ────────────────────────────────────────────────────────────

  /**
   * 지표 타입에 대한 파라미터를 반환.
   * DB 저장값 → defaultParams 순으로 우선순위 적용.
   */
  const getParams = useCallback(
    (
      type: string,
      defaults?: Record<string, number | string | boolean>
    ): Record<string, number | string | boolean> => {
      const dbParams = _cache?.[type] ?? {};
      const fallback = defaults ?? getIndicatorDef(type)?.defaultParams ?? {};
      const merged = { ...fallback, ...dbParams } as Record<string, number | string | boolean>;
      if (type === 'SMA') {
        return normalizeSmaConfig({ id: '', type: 'SMA', params: merged }).params;
      }
      if (type === 'IchimokuCloud') {
        return normalizeIchimokuConfig({ id: '', type: 'IchimokuCloud', params: merged }).params;
      }
      return merged;
    },
    []
  );

  /** 특정 지표 파라미터를 DB에 저장하고 캐시를 업데이트 */
  const saveParams = useCallback(
    (type: string, params: Record<string, number | string | boolean>) => {
      if (_cache) {
        _cache = { ..._cache, [type]: params as ParamMap };
      } else {
        _cache = { [type]: params as ParamMap };
      }
      saveIndicatorSettings(type, params as ParamMap).catch(err =>
        console.error(`[useIndicatorSettings] saveParams failed for ${type}`, err)
      );
    },
    []
  );

  /** 현재 활성 지표 목록 전체를 DB에 저장 */
  const saveAll = useCallback(
    (allParams: AllSettings) => {
      _cache = { ...allParams };
      saveAllIndicatorSettings(allParams).catch(err =>
        console.error('[useIndicatorSettings] saveAll failed', err)
      );
    },
    []
  );

  // ── 시각 설정 (색상·선굵기·수평선) ──────────────────────────────────────

  /**
   * 지표의 시각 설정을 반환.
   * DB 저장값 → registry defaults 순으로 우선순위 적용.
   *
   * @param type           지표 타입 (e.g. "RSI")
   * @param defaultPlots   없을 경우 사용할 기본 플롯 (indicatorRegistry.plots)
   * @param defaultHlines  없을 경우 사용할 기본 수평선 (indicatorRegistry.hlines)
   */
  const getVisualConfig = useCallback(
    (
      type: string,
      defaultPlots?: PlotDef[],
      defaultHlines?: HLineDef[]
    ): { plots: PlotDef[]; hlines: HLineDef[]; cloudColors?: IchimokuCloudColors } => {
      const saved = _visualCache?.[type];
      const def = getIndicatorDef(type);
      const registryPlots = defaultPlots ?? def?.plots ?? [];
      let plots = mergePlotDefs(saved?.plots as PlotDef[] | undefined, registryPlots);
      const registryHlines = defaultHlines ?? def?.hlines ?? [];
      const rawHlines = (saved?.hlines as HLineDef[] | undefined) ?? registryHlines;
      const hlines = normalizeHLines(rawHlines, type, registryHlines);

      if (type === 'SMA') {
        plots = normalizeSmaConfig({
          id: '',
          type: 'SMA',
          params: createDefaultSmaParams(),
          plots,
        }).plots ?? createDefaultSmaPlots();
      }

      if (type === 'IchimokuCloud') {
        plots = mergeIchimokuPlots(plots, registryPlots);
      }

      const cloudColors = type === 'IchimokuCloud'
        ? resolveIchimokuCloudColors(saved?.cloudColors ?? DEFAULT_ICHIMOKU_CLOUD_COLORS)
        : undefined;

      // 깊은 복사: 여러 슬롯이 같은 참조를 공유하지 않도록
      return {
        plots:  plots.map(p => ({ ...p })),
        hlines: hlines.map(h => ({ ...h })),
        cloudColors: cloudColors ? { ...cloudColors } : undefined,
      };
    },
    []
  );

  /**
   * 지표의 시각 설정을 DB에 저장하고 캐시를 업데이트.
   * IndicatorSettingsModal 저장 콜백에서 호출.
   */
  const saveVisual = useCallback(
    (
      type: string,
      plots?: PlotDef[],
      hlines?: HLineDef[],
      cloudColors?: IchimokuCloudColors,
    ) => {
      const visual: IndicatorVisual = { plots, hlines };
      if (cloudColors) visual.cloudColors = cloudColors;
      if (_visualCache) {
        _visualCache = { ..._visualCache, [type]: visual };
      } else {
        _visualCache = { [type]: visual };
      }
      saveIndicatorVisualSettings(type, visual as { plots?: unknown[]; hlines?: unknown[]; cloudColors?: IchimokuCloudColors }).catch(err =>
        console.error(`[useIndicatorSettings] saveVisual failed for ${type}`, err)
      );
    },
    []
  );

  return { getParams, saveParams, saveAll, getVisualConfig, saveVisual };
}
