/**
 * 설정 화면 — 보조지표 기본값 (Main 16종 상단 + 전체 지표, 검색 필터)
 */
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import type { IndicatorConfig } from '../types';
import type { PlotDef, HLineDef } from '../utils/indicatorRegistry';
import { buildMainIndicatorConfig } from '../utils/indicatorMainConfig';
import { indicatorDefaultsFingerprint } from '../utils/indicatorDefaultsFingerprint';
import IndicatorSettingsForm from './IndicatorSettingsForm';
import { resetConfigToDefaults } from '../utils/indicatorSettingsEditor';
import type { IchimokuCloudColors } from '../utils/ichimokuConfig';
import {
  getSettingsIndicatorTypes,
  filterSettingsIndicatorTypes,
  partitionFilteredTypes,
} from '../utils/indicatorSettingsList';
import IndicatorSettingsListSearch from './IndicatorSettingsListSearch';
import IndicatorSettingsListRow from './IndicatorSettingsListRow';
import { MAIN_INDICATOR_TYPES } from '../utils/indicatorMainTab';
import { useIndicatorListOrder } from '../hooks/useIndicatorListOrder';

export interface IndicatorSaveUiState {
  save: () => Promise<void>;
  dirty: boolean;
  saving: boolean;
  saveMessage: string | null;
}

export interface IndicatorMainDefaultsPanelProps {
  chartIndicators: IndicatorConfig[];
  onAddToChart: (type: string, config?: IndicatorConfig) => void;
  onRemoveFromChart: (type: string) => void;
  getParams: (type: string, defaults: Record<string, number | string | boolean>) => Record<string, number | string | boolean>;
  saveParams: (type: string, params: Record<string, number | string | boolean>) => void;
  getVisualConfig: (
    type: string,
    defaultPlots?: PlotDef[],
    defaultHlines?: HLineDef[],
  ) => { plots: PlotDef[]; hlines: HLineDef[]; cloudColors?: IchimokuCloudColors };
  saveVisual: (
    type: string,
    plots?: PlotDef[],
    hlines?: HLineDef[],
    cloudColors?: IchimokuCloudColors,
  ) => void;
  /** DB에 보조지표 기본값 일괄 저장 */
  saveAllDefaults?: (configs: Record<string, IndicatorConfig>) => Promise<void>;
  /** 상단 저장 버튼 상태 (SettingsPage 헤더 연동) */
  onSaveUiState?: (state: IndicatorSaveUiState | null) => void;
  /** DB 로드 완료·저장 후 재로드 트리거 */
  settingsRevision?: number;
  /** 목록 순서 변경 시 차트 보조지표 순서 동기화 */
  onListOrderChange?: (orderedTypes: string[]) => void;
}

const ALL_TYPES = getSettingsIndicatorTypes();

function buildDefaultsMap(
  getParams: IndicatorMainDefaultsPanelProps['getParams'],
  getVisualConfig: IndicatorMainDefaultsPanelProps['getVisualConfig'],
): Record<string, IndicatorConfig> {
  const next: Record<string, IndicatorConfig> = {};
  for (const type of ALL_TYPES) {
    const cfg = buildMainIndicatorConfig(type, [], getParams, getVisualConfig);
    if (cfg) next[type] = cfg;
  }
  return next;
}

function fingerprintMap(map: Record<string, IndicatorConfig>): string {
  return ALL_TYPES.map(t => map[t] ? indicatorDefaultsFingerprint(map[t]) : '').join('|');
}

const IndicatorMainDefaultsPanel: React.FC<IndicatorMainDefaultsPanelProps> = ({
  chartIndicators,
  onAddToChart,
  onRemoveFromChart,
  getParams,
  getVisualConfig,
  saveAllDefaults,
  onSaveUiState,
  settingsRevision = 0,
  onListOrderChange,
}) => {
  const onChartTypes = useMemo(() => new Set(chartIndicators.map(i => i.type)), [chartIndicators]);
  const { listOrder, moveType } = useIndicatorListOrder(onListOrderChange);
  const [draggingType, setDraggingType] = useState<string | null>(null);
  const [dragOverType, setDragOverType] = useState<string | null>(null);
  const [expandedTypes, setExpandedTypes] = useState<Set<string>>(() => new Set());
  const [configs, setConfigs] = useState<Record<string, IndicatorConfig>>({});
  const [baselineFp, setBaselineFp] = useState('');
  const [search, setSearch] = useState('');
  const [saving, setSaving] = useState(false);
  const [saveMessage, setSaveMessage] = useState<string | null>(null);

  const reloadFromDb = useCallback(() => {
    const next = buildDefaultsMap(getParams, getVisualConfig);
    setConfigs(next);
    setBaselineFp(fingerprintMap(next));
    setSaveMessage(null);
  }, [getParams, getVisualConfig]);

  useEffect(() => {
    reloadFromDb();
  }, [reloadFromDb, settingsRevision]);

  useEffect(() => {
    const clearDrag = () => {
      setDraggingType(null);
      setDragOverType(null);
    };
    document.addEventListener('dragend', clearDrag);
    return () => document.removeEventListener('dragend', clearDrag);
  }, []);

  const dirty = useMemo(
    () => baselineFp !== '' && fingerprintMap(configs) !== baselineFp,
    [configs, baselineFp],
  );

  const filtered = useMemo(
    () => filterSettingsIndicatorTypes(listOrder, search),
    [listOrder, search],
  );
  const { main: filteredMain, other: filteredOther } = useMemo(
    () => partitionFilteredTypes(filtered),
    [filtered],
  );

  const toggleExpand = useCallback((type: string) => {
    setExpandedTypes(prev => {
      const next = new Set(prev);
      if (next.has(type)) next.delete(type);
      else next.add(type);
      return next;
    });
  }, []);

  const handleConfigChange = useCallback((type: string, updated: IndicatorConfig) => {
    setConfigs(prev => ({ ...prev, [type]: updated }));
    setSaveMessage(null);
  }, []);

  const handleToggleChart = useCallback((type: string, enabled: boolean) => {
    if (enabled) {
      onAddToChart(type, configs[type]);
    } else {
      onRemoveFromChart(type);
    }
  }, [configs, onAddToChart, onRemoveFromChart]);

  const handleRowDefaults = useCallback((type: string) => {
    const base = configs[type];
    if (!base) return;
    const reset = resetConfigToDefaults(base);
    handleConfigChange(type, reset);
  }, [configs, handleConfigChange]);

  const handleResetAll = useCallback(() => {
    if (!window.confirm('목록에 있는 모든 보조지표 기본값을 초기화할까요? (저장 버튼을 눌러야 DB에 반영됩니다)')) return;
    const next: Record<string, IndicatorConfig> = {};
    for (const type of ALL_TYPES) {
      const base = configs[type] ?? buildMainIndicatorConfig(type, [], getParams, getVisualConfig);
      if (!base) continue;
      next[type] = resetConfigToDefaults(base);
    }
    setConfigs(next);
    setSaveMessage(null);
  }, [configs, getParams, getVisualConfig]);

  const handleSaveAll = useCallback(async () => {
    if (!saveAllDefaults) {
      setSaveMessage('저장 API를 사용할 수 없습니다.');
      return;
    }
    if (!dirty) return;
    setSaving(true);
    setSaveMessage(null);
    try {
      await saveAllDefaults(configs);
      const fp = fingerprintMap(configs);
      setBaselineFp(fp);
      setSaveMessage('저장되었습니다.');
    } catch (err) {
      console.error('[IndicatorMainDefaultsPanel] save failed', err);
      setSaveMessage('저장에 실패했습니다. 다시 시도해 주세요.');
    } finally {
      setSaving(false);
    }
  }, [saveAllDefaults, configs, dirty]);

  useEffect(() => {
    if (!onSaveUiState) return;
    onSaveUiState({
      save: handleSaveAll,
      dirty,
      saving,
      saveMessage,
    });
    return () => onSaveUiState(null);
  }, [onSaveUiState, handleSaveAll, dirty, saving, saveMessage]);

  const canReorder = !search.trim();

  const renderRows = (types: string[]) => types.map(type => {
    const cfg = configs[type];
    if (!cfg) return null;
    return (
      <IndicatorSettingsListRow
        key={type}
        type={type}
        config={cfg}
        enabled={onChartTypes.has(type)}
        expanded={expandedTypes.has(type)}
        variant="settings"
        draggable={canReorder}
        isDragOver={canReorder && dragOverType === type && draggingType !== type}
        onDragHandleStart={e => {
          setDraggingType(type);
          e.dataTransfer.setData('text/indicator-type', type);
          e.dataTransfer.effectAllowed = 'move';
        }}
        onDragOver={e => {
          if (!draggingType || draggingType === type) return;
          e.preventDefault();
          e.dataTransfer.dropEffect = 'move';
          setDragOverType(type);
        }}
        onDragLeave={() => {
          if (dragOverType === type) setDragOverType(null);
        }}
        onDrop={e => {
          e.preventDefault();
          const from = e.dataTransfer.getData('text/indicator-type') || draggingType;
          if (from && from !== type) moveType(from, type, 'before');
          setDraggingType(null);
          setDragOverType(null);
        }}
        onToggleExpand={() => toggleExpand(type)}
        onToggleEnabled={on => handleToggleChart(type, on)}
        onChange={updated => handleConfigChange(type, updated)}
        onRowDefaults={() => handleRowDefaults(type)}
      />
    );
  });

  return (
    <>
      <div className="stg-ind-intro">
        <p>
          지표 추가 팝업 <strong>Main</strong> 탭 {MAIN_INDICATOR_TYPES.length}종을 상단에 두었고, 그 아래에 등록된 모든 보조지표가 있습니다.
          우측 스위치로 차트에 바로 추가·제거할 수 있습니다. <strong>⠿</strong> 핸들로 목록 순서를 바꿀 수 있으며, 차트에 표시되는 보조지표 pane 순서도 이 목록을 따릅니다.
          파라미터·색상을 변경한 뒤 <strong>상단 저장</strong> 버튼을 눌러 DB에 반영하세요.
        </p>
        <button type="button" className="stg-ind-reset-all" onClick={handleResetAll}>
          전체 기본값 복원
        </button>
      </div>

      <IndicatorSettingsListSearch
        value={search}
        onChange={setSearch}
        totalCount={listOrder.length}
        filteredCount={filtered.length}
        className="stg-ind-search-block"
      />

      <div className="stg-ind-list">
        {filtered.length === 0 ? (
          <div className="no-results ind-settings-no-results">
            &apos;{search}&apos; 검색 결과 없음
          </div>
        ) : (
          <>
            {filteredMain.length > 0 && (
              <section className="ind-settings-section">
                <h3 className="ind-settings-section-title">
                  Main 보조지표 <span className="ind-settings-section-count">{filteredMain.length}</span>
                </h3>
                {renderRows(filteredMain)}
              </section>
            )}
            {filteredOther.length > 0 && (
              <section className="ind-settings-section">
                <h3 className="ind-settings-section-title">
                  기타 보조지표 <span className="ind-settings-section-count">{filteredOther.length}</span>
                </h3>
                {renderRows(filteredOther)}
              </section>
            )}
          </>
        )}
      </div>
    </>
  );
};

export default IndicatorMainDefaultsPanel;
