/**
 * 지표 추가 팝업 Main 탭 — 설정 초기화·차트 인스턴스 병합
 */
import type { IndicatorConfig } from '../types';
import type { PlotDef, HLineDef } from './indicatorRegistry';
import { getIndicatorDef, enrichIndicatorConfig } from './indicatorRegistry';
import { MAIN_INDICATOR_TYPES } from './indicatorMainTab';
import { getSettingsIndicatorTypes } from './indicatorSettingsList';
import { initializeIndicatorConfigForEditor } from './indicatorSettingsEditor';
import {
  normalizeSmaConfig,
  createDefaultSmaPlotVisibility,
} from './smaConfig';
import { normalizeIchimokuConfig } from './ichimokuConfig';
import type { IchimokuCloudColors } from './ichimokuConfig';
import { isMainIndicatorType } from './indicatorMainTab';

export type MainIndicatorDraftMap = Record<string, IndicatorConfig>;

/** 지표 추가 팝업에서 차트 미적용 지표 설정용 modal id 접두사 */
export const INDICATOR_SETTINGS_TEMPLATE_PREFIX = 'template:';

export function indicatorSettingsTemplateId(type: string): string {
  return `${INDICATOR_SETTINGS_TEMPLATE_PREFIX}${type}`;
}

export function isIndicatorSettingsTemplateId(id: string): boolean {
  return id.startsWith(INDICATOR_SETTINGS_TEMPLATE_PREFIX);
}

export function indicatorTypeFromSettingsId(id: string): string | null {
  if (!isIndicatorSettingsTemplateId(id)) return null;
  return id.slice(INDICATOR_SETTINGS_TEMPLATE_PREFIX.length);
}

export function buildMainIndicatorConfig(
  type: string,
  activeIndicators: IndicatorConfig[],
  getParams: (type: string, defaults: Record<string, number | string | boolean>) => Record<string, number | string | boolean>,
  getVisualConfig: (
    type: string,
    defaultPlots?: PlotDef[],
    defaultHlines?: HLineDef[],
  ) => { plots: PlotDef[]; hlines: HLineDef[]; cloudColors?: IchimokuCloudColors },
): IndicatorConfig | null {
  const def = getIndicatorDef(type);
  if (!def) return null;
  const active = activeIndicators.find(i => i.type === type);
  const base: IndicatorConfig = active ?? {
    id: `template_${type}`,
    type,
    params: {},
    plots: [],
    hlines: [],
  };
  return initializeIndicatorConfigForEditor(base, getParams, getVisualConfig);
}

/** Main 탭 16종 전체 설정 맵 (차트에 없어도 DB 기본값 편집용) */
export function buildMainIndicatorDraftMap(
  activeIndicators: IndicatorConfig[],
  getParams: (type: string, defaults: Record<string, number | string | boolean>) => Record<string, number | string | boolean>,
  getVisualConfig: (
    type: string,
    defaultPlots?: PlotDef[],
    defaultHlines?: HLineDef[],
  ) => { plots: PlotDef[]; hlines: HLineDef[]; cloudColors?: IchimokuCloudColors },
): MainIndicatorDraftMap {
  const map: MainIndicatorDraftMap = {};
  for (const type of MAIN_INDICATOR_TYPES) {
    const cfg = buildMainIndicatorConfig(type, activeIndicators, getParams, getVisualConfig);
    if (cfg) map[type] = cfg;
  }
  return map;
}

export function newMainIndicatorId(): string {
  return `ind_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
}

function finalizeMainIndicatorConfig(cfg: IndicatorConfig, isNew: boolean): IndicatorConfig {
  let out = enrichIndicatorConfig(cfg);
  if (out.type === 'SMA') {
    out = normalizeSmaConfig({
      ...out,
      plotVisibility: isNew
        ? (out.plotVisibility ?? createDefaultSmaPlotVisibility())
        : out.plotVisibility,
    });
  } else if (out.type === 'IchimokuCloud') {
    out = normalizeIchimokuConfig(out);
  }
  return out;
}

/** Main 탭 설정 → 현재 차트에 올라간 동일 type 인스턴스에 반영 (id·hidden 유지) */
export function mergeMainDraftOntoChart(
  activeIndicators: IndicatorConfig[],
  draftByType: MainIndicatorDraftMap,
): IndicatorConfig[] {
  return activeIndicators.map(ind => {
    const tpl = draftByType[ind.type];
    if (!tpl) return enrichIndicatorConfig(ind);
    return finalizeMainIndicatorConfig(
      { ...tpl, id: ind.id, hidden: ind.hidden },
      false,
    );
  });
}

/**
 * Main 탭 일괄/설정 적용 — enabledTypes 에 포함된 지표만 차트에 남기고,
 * 새로 켠 type 은 draft 설정으로 추가, 꺼진 type 은 제거.
 * Main 탭이 아닌 지표는 그대로 유지.
 */
export function applyMainDraftToChart(
  activeIndicators: IndicatorConfig[],
  draftByType: MainIndicatorDraftMap,
  enabledTypes: ReadonlySet<string>,
): IndicatorConfig[] {
  const result: IndicatorConfig[] = activeIndicators
    .filter(ind => !isMainIndicatorType(ind.type))
    .map(ind => enrichIndicatorConfig(ind));

  const seen = new Set<string>();

  for (const ind of activeIndicators) {
    if (!isMainIndicatorType(ind.type)) continue;
    if (!enabledTypes.has(ind.type)) continue;
    seen.add(ind.type);
    const tpl = draftByType[ind.type];
    if (!tpl) {
      result.push(enrichIndicatorConfig(ind));
      continue;
    }
    result.push(finalizeMainIndicatorConfig(
      { ...tpl, id: ind.id, hidden: ind.hidden },
      false,
    ));
  }

  for (const type of MAIN_INDICATOR_TYPES) {
    if (!enabledTypes.has(type) || seen.has(type)) continue;
    const tpl = draftByType[type];
    if (!tpl) continue;
    result.push(finalizeMainIndicatorConfig(
      { ...tpl, id: newMainIndicatorId() },
      true,
    ));
  }

  return result;
}

/** 차트에 올라간 Main 탭 type 집합 */
export function mainTypesOnChart(indicators: IndicatorConfig[]): Set<string> {
  return new Set(
    indicators.filter(i => isMainIndicatorType(i.type)).map(i => i.type),
  );
}

export function mainDraftListFromMap(map: MainIndicatorDraftMap): IndicatorConfig[] {
  return MAIN_INDICATOR_TYPES
    .map(type => map[type])
    .filter((c): c is IndicatorConfig => c != null);
}

/** 설정 UI 전체 지표 draft 맵 */
export function buildAllIndicatorDraftMap(
  activeIndicators: IndicatorConfig[],
  getParams: (type: string, defaults: Record<string, number | string | boolean>) => Record<string, number | string | boolean>,
  getVisualConfig: (
    type: string,
    defaultPlots?: PlotDef[],
    defaultHlines?: HLineDef[],
  ) => { plots: PlotDef[]; hlines: HLineDef[]; cloudColors?: IchimokuCloudColors },
): MainIndicatorDraftMap {
  const map: MainIndicatorDraftMap = {};
  for (const type of getSettingsIndicatorTypes()) {
    const cfg = buildMainIndicatorConfig(type, activeIndicators, getParams, getVisualConfig);
    if (cfg) map[type] = cfg;
  }
  return map;
}

/** draft 맵 → DB 저장용 config 배열 (순서 유지) */
export function allDraftListFromMap(map: MainIndicatorDraftMap): IndicatorConfig[] {
  return getSettingsIndicatorTypes()
    .map(type => map[type])
    .filter((c): c is IndicatorConfig => c != null);
}

/** 차트에 올라간 보조지표 type 집합 (Main 외 포함) */
export function indicatorTypesOnChart(indicators: IndicatorConfig[]): Set<string> {
  return new Set(indicators.map(i => i.type));
}

const MANAGED_TYPES = getSettingsIndicatorTypes();
const MANAGED_SET = new Set(MANAGED_TYPES);

/**
 * 설정 UI에서 관리하는 모든 type — enabledTypes 기준으로 차트 병합.
 * 관리 대상이 아닌 type 은 변경 없이 유지.
 */
export function applyAllDraftToChart(
  activeIndicators: IndicatorConfig[],
  draftByType: MainIndicatorDraftMap,
  enabledTypes: ReadonlySet<string>,
): IndicatorConfig[] {
  const result: IndicatorConfig[] = activeIndicators
    .filter(ind => !MANAGED_SET.has(ind.type))
    .map(ind => enrichIndicatorConfig(ind));

  const seen = new Set<string>();

  for (const ind of activeIndicators) {
    if (!MANAGED_SET.has(ind.type)) continue;
    if (!enabledTypes.has(ind.type)) continue;
    seen.add(ind.type);
    const tpl = draftByType[ind.type];
    if (!tpl) {
      result.push(enrichIndicatorConfig(ind));
      continue;
    }
    result.push(finalizeMainIndicatorConfig(
      { ...tpl, id: ind.id, hidden: ind.hidden },
      false,
    ));
  }

  for (const type of MANAGED_TYPES) {
    if (!enabledTypes.has(type) || seen.has(type)) continue;
    const tpl = draftByType[type];
    if (!tpl) continue;
    result.push(finalizeMainIndicatorConfig(
      { ...tpl, id: newMainIndicatorId() },
      true,
    ));
  }

  return result;
}
