import './index.css';
import type { ThemeConfig } from '../../themes/types';
import { IBimComponent } from '../../types/component';
import { localeManager, t } from '../../services/locale';
import { themeManager } from '../../services/theme';
import type { MeasureMode, MeasurePanelOptions, MeasureResult } from './types';

/**
 * 测量面板组件（只做 UI，不实现真实测量）
 *
 * 组件职责：
 * - 展示 8 种测量方式按钮（默认 4 个，可展开/收起）
 * - 维护当前选中的测量方式（current mode）
 * - 展示测量结果（由外部 setResult 注入）
 * - 提供 “删除全部 / 设置” 的 UI 与对外方法（暂不实现真实逻辑，仅回调/占位）
 *
 * 注意：
 * - 所有用户可见文本必须通过 t(key) 获取（国际化强制要求）
 * - 组件需要订阅主题/语言变更，并在 destroy 时清理订阅
 */
export class MeasurePanel implements IBimComponent {
  public element: HTMLElement;

  private options: MeasurePanelOptions;
  private activeMode: MeasureMode;
  private isExpanded: boolean;
  private result: MeasureResult | null = null;

  // DOM 引用（便于局部更新，减少频繁 querySelector）
  private toolButtons: Map<MeasureMode, HTMLButtonElement> = new Map();
  private toggleBtn!: HTMLButtonElement;
  private toggleTextEl!: HTMLElement;
  private currentModeValueEl!: HTMLElement;
  private mainValueValueEl!: HTMLElement;
  private mainValueLabelEl!: HTMLElement;
  private xyzXEl!: HTMLElement;
  private xyzYEl!: HTMLElement;
  private xyzZEl!: HTMLElement;
  private clearBtn!: HTMLButtonElement;
  private settingsBtn!: HTMLButtonElement;

  // 订阅清理
  private unsubscribeLocale: (() => void) | null = null;
  private unsubscribeTheme: (() => void) | null = null;

  /**
   * 构造函数
   * @param options 组件配置
   */
  constructor(options: MeasurePanelOptions = {}) {
    this.options = options;
    this.activeMode = options.defaultMode ?? 'distance';
    this.isExpanded = options.defaultExpanded ?? false;

    this.element = this.createDom();
  }

  /**
   * 初始化组件（实现 IBimComponent）
   */
  public init(): void {
    // 订阅语言变更：更新所有文本/提示
    this.unsubscribeLocale = localeManager.subscribe(() => {
      this.setLocales();
    });

    // 订阅主题变更：更新 CSS 变量（如需要）
    this.unsubscribeTheme = themeManager.subscribe((theme) => {
      this.setTheme(theme);
    });

    // 初始应用
    this.setLocales();
    this.setTheme(themeManager.getTheme());

    // 初始渲染状态（按钮显隐、选中态、结果区）
    this.applyExpandedState();
    this.applyActiveModeState();
    this.renderResult();
  }

  /**
   * 设置主题（实现 IBimComponent）
   * @param theme 主题配置
   */
  public setTheme(theme: ThemeConfig): void {
    // 为了可读性：这里显式写出映射，不做过度抽象
    const style = this.element.style;

    // 这些变量不会强制覆盖外部（Dialog）已有变量，只做兜底
    style.setProperty('--bim-measure-border', theme.border ?? 'rgba(255, 255, 255, 0.12)');
    style.setProperty('--bim-measure-divider', theme.border ?? 'rgba(255, 255, 255, 0.10)');
    style.setProperty('--bim-measure-icon-color', theme.icon ?? '#ddd');
    style.setProperty('--bim-measure-label-color', theme.textSecondary ?? 'rgba(255, 255, 255, 0.70)');
    style.setProperty('--bim-measure-value-color', theme.textPrimary ?? 'rgba(255, 255, 255, 0.90)');

    // “删除全部”颜色：截图中偏绿色，这里用 primary 做一个合理映射
    style.setProperty('--bim-measure-danger', theme.primary ?? '#46d369');
    style.setProperty('--bim-measure-btn-bg', theme.componentBackground ?? 'rgba(255, 255, 255, 0.06)');
    style.setProperty('--bim-measure-btn-hover-bg', theme.componentHover ?? 'rgba(255, 255, 255, 0.10)');
    style.setProperty('--bim-measure-btn-active-bg', theme.componentActive ?? 'rgba(255, 255, 255, 0.14)');
  }

  /**
   * 设置语言（实现 IBimComponent）
   */
  public setLocales(): void {
    // 1) 更新按钮 tooltip（图标占位时，tooltip 是主要的可读文本）
    for (const [mode, btn] of this.toolButtons.entries()) {
      btn.title = t(this.getModeI18nKey(mode));
      btn.setAttribute('aria-label', btn.title);
    }

    // 2) 更新展开/收起按钮 tooltip
    this.toggleBtn.title = this.isExpanded ? t('measure.actions.collapse') : t('measure.actions.expand');
    this.toggleBtn.setAttribute('aria-label', this.toggleBtn.title);

    // 2.1) 更新展开/收起按钮可见文本（你要求的“文字提示”）
    if (this.toggleTextEl) {
      this.toggleTextEl.textContent = this.toggleBtn.title;
    }

    // 3) 更新底部按钮文本/tooltip
    this.clearBtn.textContent = t('measure.actions.clearAll');
    this.settingsBtn.title = t('measure.actions.settings');
    this.settingsBtn.setAttribute('aria-label', this.settingsBtn.title);

    // 4) 更新“当前方式”显示（value）
    this.currentModeValueEl.textContent = t(this.getModeI18nKey(this.activeMode));

    // 5) 主值 label（随模式变化）
    this.mainValueLabelEl.textContent = t(this.getModeValueLabelI18nKey(this.activeMode));

    // 6) XYZ label（使用 key）
    // 这里 label 在 createDom 已经是固定文本节点，直接用 setText 更新更直观
    // 但为了减少 DOM 结构复杂度，我们把 label 写在 createDom 里，通过 data-key 更新
    const labelNodes = this.element.querySelectorAll<HTMLElement>('[data-i18n-key]');
    labelNodes.forEach((node) => {
      const key = node.dataset.i18nKey;
      if (key) node.textContent = t(key);
    });
  }

  /**
   * 销毁组件（实现 IBimComponent）
   */
  public destroy(): void {
    // 清理订阅
    if (this.unsubscribeLocale) {
      this.unsubscribeLocale();
      this.unsubscribeLocale = null;
    }
    if (this.unsubscribeTheme) {
      this.unsubscribeTheme();
      this.unsubscribeTheme = null;
    }

    // 清理事件监听：由于本组件的监听都绑定在创建时的具体按钮上，
    // 且按钮会随 element 一起被 GC，这里不做逐个 removeEventListener（可读性优先）

    // 移除 DOM
    this.element.remove();
  }

  // ==========================
  // 对外 API（给 Manager / 外部业务调用）
  // ==========================

  /**
   * 获取当前测量方式
   */
  public getActiveMode(): MeasureMode {
    return this.activeMode;
  }

  /**
   * 切换测量方式（你要求的“切换类型的方法”）
   * @param mode 目标测量方式
   */
  public switchMode(mode: MeasureMode): void {
    this.setActiveMode(mode);
  }

  /**
   * 设置当前测量方式
   * @param mode 目标测量方式
   */
  public setActiveMode(mode: MeasureMode): void {
    if (this.activeMode === mode) return;
    this.activeMode = mode;
    this.applyActiveModeState();

    // 切换方式后，主值 label 也需要更新
    this.mainValueLabelEl.textContent = t(this.getModeValueLabelI18nKey(this.activeMode));
    this.currentModeValueEl.textContent = t(this.getModeI18nKey(this.activeMode));

    // 通知外部（如果需要）
    if (this.options.onModeChange) {
      this.options.onModeChange(mode);
    }

    // 模式切换后，结果展示也应刷新（例如某些字段显示为 --）
    this.renderResult();
  }

  /**
   * 设置测量结果（由外部注入）
   * @param result 测量结果；传 null 表示清空
   */
  public setResult(result: MeasureResult | null): void {
    this.result = result;
    this.renderResult();
  }

  /**
   * 删除全部（只做 UI 状态清空 + 回调）
   */
  public clearAll(): void {
    // 先清空结果显示
    this.result = null;
    this.renderResult();

    // 通知外部
    if (this.options.onClearAll) {
      this.options.onClearAll();
    }
  }

  /**
   * 打开设置（本次只预留方法/回调）
   */
  public openSettings(): void {
    if (this.options.onSettings) {
      this.options.onSettings();
      return;
    }

    // 兜底：避免无声失败，打印中文日志（符合项目规范）
    console.warn('[MeasurePanel] 未提供设置回调 onSettings，当前仅预留接口。');
  }

  /**
   * 展开 / 收起（可选对外调用）
   * @param expanded 是否展开
   */
  public setExpanded(expanded: boolean): void {
    if (this.isExpanded === expanded) return;
    this.isExpanded = expanded;
    this.applyExpandedState();
    this.setLocales(); // 更新 tooltip（展开/收起）

    // 通知外部：用于重新计算 Dialog 高度
    if (this.options.onExpandedChange) {
      this.options.onExpandedChange(this.isExpanded);
    }
  }

  /**
   * 获取是否展开
   */
  public getExpanded(): boolean {
    return this.isExpanded;
  }

  // ==========================
  // 内部实现
  // ==========================

  private createDom(): HTMLElement {
    const root = document.createElement('div');
    root.className = 'bim-measure-panel';

    // 顶部：工具按钮区
    const toolsBox = document.createElement('div');
    toolsBox.className = 'bim-measure-tools';

    const grid = document.createElement('div');
    grid.className = 'bim-measure-tool-grid';

    // 8 种测量方式（顺序严格按你给的）
    const modes: MeasureMode[] = [
      'distance',
      'minDistance',
      'angle',
      'elevation',
      'volume',
      'laserDistance',
      'slope',
      'spaceVolume'
    ];

    // 图标占位：统一用圆形（你要求的“圆形占位”）
    const circleIconSvg = `
      <svg viewBox="0 0 24 24" aria-hidden="true">
        <circle cx="12" cy="12" r="9"></circle>
      </svg>
    `;

    // 逐个创建按钮
    for (let i = 0; i < modes.length; i++) {
      const mode = modes[i];
      const btn = document.createElement('button');
      btn.type = 'button';
      btn.className = 'bim-measure-tool-btn';
      btn.dataset.mode = mode;

      // icon
      const icon = document.createElement('span');
      icon.className = 'bim-measure-tool-icon';
      icon.innerHTML = circleIconSvg;
      btn.appendChild(icon);

      // 点击切换模式
      btn.addEventListener('click', () => {
        this.setActiveMode(mode);
      });

      // 先不在这里设置 title/text（统一交给 setLocales）
      this.toolButtons.set(mode, btn);
      grid.appendChild(btn);
    }

    toolsBox.appendChild(grid);

    // 展开/收起按钮（箭头）
    const toggleBox = document.createElement('div');
    toggleBox.className = 'bim-measure-toggle';

    this.toggleBtn = document.createElement('button');
    this.toggleBtn.type = 'button';
    this.toggleBtn.className = 'bim-measure-toggle-btn';
    // 展开/收起按钮：更小，并带文字提示（展开/收起）
    // 注意：文本内容由 setLocales() 统一更新，这里先放一个占位容器
    this.toggleTextEl = document.createElement('span');
    this.toggleTextEl.className = 'bim-measure-toggle-text';
    const toggleIconEl = document.createElement('span');
    toggleIconEl.className = 'bim-measure-toggle-icon';
    toggleIconEl.innerHTML = `
      <svg viewBox="0 0 24 24" aria-hidden="true">
        <path d="M7 10l5 5 5-5z"></path>
      </svg>
    `;
    this.toggleBtn.appendChild(this.toggleTextEl);
    this.toggleBtn.appendChild(toggleIconEl);
    this.toggleBtn.addEventListener('click', () => {
      this.isExpanded = !this.isExpanded;
      this.applyExpandedState();
      this.setLocales(); // 更新 tooltip（展开/收起）

      // 通知外部：用于重新计算 Dialog 高度
      if (this.options.onExpandedChange) {
        this.options.onExpandedChange(this.isExpanded);
      }
    });

    toggleBox.appendChild(this.toggleBtn);
    toolsBox.appendChild(toggleBox);
    root.appendChild(toolsBox);

    // 中部：结果区
    const resultBox = document.createElement('div');
    resultBox.className = 'bim-measure-result';

    // 当前方式
    const currentModeRow = document.createElement('div');
    currentModeRow.className = 'bim-measure-row';
    const currentModeLabel = document.createElement('span');
    currentModeLabel.className = 'label';
    currentModeLabel.dataset.i18nKey = 'measure.labels.currentMode';
    const currentModeValue = document.createElement('span');
    currentModeValue.className = 'value';
    this.currentModeValueEl = currentModeValue;
    currentModeRow.appendChild(currentModeLabel);
    currentModeRow.appendChild(currentModeValue);
    resultBox.appendChild(currentModeRow);

    // 主结果值（随模式变化）
    const mainValueRow = document.createElement('div');
    mainValueRow.className = 'bim-measure-row';
    const mainValueLabel = document.createElement('span');
    mainValueLabel.className = 'label';
    this.mainValueLabelEl = mainValueLabel;
    const mainValueValue = document.createElement('span');
    mainValueValue.className = 'value';
    this.mainValueValueEl = mainValueValue;
    mainValueRow.appendChild(mainValueLabel);
    mainValueRow.appendChild(mainValueValue);
    resultBox.appendChild(mainValueRow);

    // XYZ
    const xyzBox = document.createElement('div');
    xyzBox.className = 'bim-measure-xyz';

    const makeXyzRow = (labelKey: string, valueElSetter: (el: HTMLElement) => void) => {
      const row = document.createElement('div');
      row.className = 'bim-measure-row';
      const label = document.createElement('span');
      label.className = 'label';
      label.dataset.i18nKey = labelKey;
      const value = document.createElement('span');
      value.className = 'value';
      valueElSetter(value);
      row.appendChild(label);
      row.appendChild(value);
      return row;
    };

    xyzBox.appendChild(makeXyzRow('measure.labels.x', (el) => (this.xyzXEl = el)));
    xyzBox.appendChild(makeXyzRow('measure.labels.y', (el) => (this.xyzYEl = el)));
    xyzBox.appendChild(makeXyzRow('measure.labels.z', (el) => (this.xyzZEl = el)));
    resultBox.appendChild(xyzBox);

    root.appendChild(resultBox);

    // 底部：删除全部 + 设置
    const footer = document.createElement('div');
    footer.className = 'bim-measure-footer';

    this.clearBtn = document.createElement('button');
    this.clearBtn.type = 'button';
    this.clearBtn.className = 'bim-measure-clear-btn';
    this.clearBtn.addEventListener('click', () => {
      this.clearAll();
    });

    this.settingsBtn = document.createElement('button');
    this.settingsBtn.type = 'button';
    this.settingsBtn.className = 'bim-measure-settings-btn';
    this.settingsBtn.innerHTML = `
      <svg viewBox="0 0 24 24" aria-hidden="true">
        <path d="M19.14 12.94c.04-.31.06-.63.06-.94s-.02-.63-.06-.94l2.03-1.58a.5.5 0 0 0 .12-.64l-1.92-3.32a.5.5 0 0 0-.6-.22l-2.39.96a7.27 7.27 0 0 0-1.63-.94l-.36-2.54A.5.5 0 0 0 13.9 1h-3.8a.5.5 0 0 0-.49.42l-.36 2.54c-.58.23-1.12.54-1.63.94l-2.39-.96a.5.5 0 0 0-.6.22L2.71 7.48a.5.5 0 0 0 .12.64l2.03 1.58c-.04.31-.06.63-.06.94s.02.63.06.94L2.83 14.52a.5.5 0 0 0-.12.64l1.92 3.32c.13.22.39.3.6.22l2.39-.96c.5.4 1.05.71 1.63.94l.36 2.54c.04.24.25.42.49.42h3.8c.24 0 .45-.18.49-.42l.36-2.54c.58-.23 1.12-.54 1.63-.94l2.39.96c.22.09.47 0 .6-.22l1.92-3.32a.5.5 0 0 0-.12-.64l-2.03-1.58zM12 15.5A3.5 3.5 0 1 1 12 8a3.5 3.5 0 0 1 0 7.5z"></path>
      </svg>
    `;
    this.settingsBtn.addEventListener('click', () => {
      this.openSettings();
    });

    footer.appendChild(this.clearBtn);
    footer.appendChild(this.settingsBtn);
    root.appendChild(footer);

    return root;
  }

  /**
   * 应用“展开/收起”状态：默认只显示前 4 个按钮
   */
  private applyExpandedState(): void {
    let index = 0;
    for (const btn of this.toolButtons.values()) {
      // 默认展示前四个，其余根据展开状态显示/隐藏
      if (index >= 4) {
        btn.style.display = this.isExpanded ? '' : 'none';
      } else {
        btn.style.display = '';
      }
      index++;
    }

    // toggle 样式（旋转箭头）
    if (this.isExpanded) {
      this.toggleBtn.classList.add('is-expanded');
    } else {
      this.toggleBtn.classList.remove('is-expanded');
    }
  }

  /**
   * 应用“当前选中按钮”样式
   */
  private applyActiveModeState(): void {
    for (const [mode, btn] of this.toolButtons.entries()) {
      if (mode === this.activeMode) {
        btn.classList.add('is-active');
      } else {
        btn.classList.remove('is-active');
      }
    }
  }

  /**
   * 渲染结果区（根据 activeMode 从 result 里取对应字段）
   */
  private renderResult(): void {
    // 1) 主值
    const mainText = this.formatMainValue(this.activeMode, this.result);
    this.mainValueValueEl.textContent = mainText;

    // 2) XYZ
    const xyz = this.result?.xyz;
    if (!xyz) {
      this.xyzXEl.textContent = '--';
      this.xyzYEl.textContent = '--';
      this.xyzZEl.textContent = '--';
      return;
    }

    // 为了可读性：这里不做 fancy formatter，只做基础展示
    this.xyzXEl.textContent = this.formatNumber(xyz.x);
    this.xyzYEl.textContent = this.formatNumber(xyz.y);
    this.xyzZEl.textContent = this.formatNumber(xyz.z);
  }

  /**
   * 获取模式名称的国际化 key
   */
  private getModeI18nKey(mode: MeasureMode): string {
    return `measure.modes.${mode}`;
  }

  /**
   * 获取“主值 label”的国际化 key（随模式变化）
   */
  private getModeValueLabelI18nKey(mode: MeasureMode): string {
    return `measure.labels.value.${mode}`;
  }

  /**
   * 将“当前模式”的主值格式化为文本
   * @param mode 当前模式
   * @param result 当前结果
   */
  private formatMainValue(mode: MeasureMode, result: MeasureResult | null): string {
    if (!result) return '--';

    // 根据不同 mode 读取对应字段并格式化单位
    // 单位文本也走国际化（可替换为英文/中文）
    switch (mode) {
      case 'distance':
        return this.formatWithUnit(result.distanceMm, 'measure.units.mm');
      case 'minDistance':
        return this.formatWithUnit(result.minDistanceMm, 'measure.units.mm');
      case 'angle':
        return this.formatWithUnit(result.angleDeg, 'measure.units.deg');
      case 'elevation':
        return this.formatWithUnit(result.elevationMm, 'measure.units.mm');
      case 'volume':
        return this.formatWithUnit(result.volumeM3, 'measure.units.m3');
      case 'laserDistance':
        return this.formatWithUnit(result.laserDistanceMm, 'measure.units.mm');
      case 'slope':
        return this.formatWithUnit(result.slopePercent, 'measure.units.percent');
      case 'spaceVolume':
        return this.formatWithUnit(result.spaceVolumeM3, 'measure.units.m3');
      default:
        return '--';
    }
  }

  /**
   * 格式化数值 + 单位（单位走国际化）
   */
  private formatWithUnit(value: number | undefined, unitKey: string): string {
    if (value === null || value === undefined || Number.isNaN(value)) return '--';
    return `${this.formatNumber(value)} ${t(unitKey)}`;
  }

  /**
   * 基础数字格式化（可读性优先）
   */
  private formatNumber(value: number): string {
    // 保留 3 位小数以内（简单策略：整数不带小数，非整数保留到 3 位）
    if (Number.isInteger(value)) return String(value);
    return value.toFixed(3).replace(/0+$/g, '').replace(/\.$/g, '');
  }
}


