import { app, BrowserWindow, ipcMain, screen } from 'electron';
import type Store from 'electron-store';

import { getSharedStore } from './config';

const store = getSharedStore();

// 默认窗口尺寸
export const DEFAULT_MAIN_WIDTH = 1200;
export const DEFAULT_MAIN_HEIGHT = 780;
export const DEFAULT_MINI_WIDTH = 340;
export const DEFAULT_MINI_HEIGHT = 64;
export const DEFAULT_MINI_EXPANDED_HEIGHT = 400;

// 用于存储窗口状态的键名
export const WINDOW_STATE_KEY = 'windowState';

// 最小窗口尺寸（确保内容不会被截断）
const ABSOLUTE_MIN_WIDTH = 900;
const ABSOLUTE_MIN_HEIGHT = 640;
let MIN_WIDTH = ABSOLUTE_MIN_WIDTH;
let MIN_HEIGHT = ABSOLUTE_MIN_HEIGHT;

// 标记IPC处理程序是否已注册
let ipcHandlersRegistered = false;

/**
 * 窗口状态类型定义
 */
export interface WindowState {
  width: number;
  height: number;
  x?: number;
  y?: number;
  isMaximized: boolean;
}

/**
 * 窗口大小管理器
 * 负责保存、恢复和维护窗口大小状态
 */
class WindowSizeManager {
  private store: Store<Record<string, unknown>>;
  private mainWindow: BrowserWindow | null = null;
  private savedState: WindowState | null = null;
  private isInitialized: boolean = false;
  private saveStateDebounceTimer: ReturnType<typeof setTimeout> | null = null;

  constructor() {
    this.store = store;
    // 初始化时不做与screen相关的操作，等app ready后再初始化
  }

  /**
   * 防抖保存窗口状态：move/resize 在拖动时每秒触发几十次，
   * 直接写 config.json 是 #714 EBUSY 争用的最大来源
   */
  private scheduleSaveWindowState(win: BrowserWindow): void {
    if (this.saveStateDebounceTimer) {
      clearTimeout(this.saveStateDebounceTimer);
    }
    this.saveStateDebounceTimer = setTimeout(() => {
      this.saveStateDebounceTimer = null;
      if (!win.isDestroyed() && !win.isMinimized()) {
        this.saveWindowState(win);
      }
    }, 500);
  }

  private flushScheduledSave(): void {
    if (this.saveStateDebounceTimer) {
      clearTimeout(this.saveStateDebounceTimer);
      this.saveStateDebounceTimer = null;
    }
  }

  /**
   * 初始化窗口大小管理器
   * 必须在app ready后调用
   */
  initialize(): void {
    if (!app.isReady()) {
      console.warn('WindowSizeManager.initialize() 必须在 app ready 之后调用！');
      return;
    }

    if (this.isInitialized) {
      return;
    }

    this.initMinimumWindowSize();
    this.setupIPCHandlers();
    this.isInitialized = true;
    console.log('窗口大小管理器初始化完成');
  }

  /**
   * 设置主窗口引用
   */
  setMainWindow(win: BrowserWindow): void {
    if (!this.isInitialized) {
      this.initialize();
    }

    this.mainWindow = win;

    // 读取保存的状态
    this.savedState = this.getWindowState();

    // 监听重要事件
    this.setupEventListeners(win);

    // 立即保存初始状态
    this.saveWindowState(win);
  }

  /**
   * 初始化最小窗口尺寸
   */
  private initMinimumWindowSize(): void {
    if (!app.isReady()) {
      console.warn('不能在 app ready 之前访问 screen 模块');
      return;
    }

    try {
      const { width: workAreaWidth, height: workAreaHeight } = screen.getPrimaryDisplay().workArea;

      // 根据工作区大小设置合理的最小尺寸，但不低于绝对最小值
      MIN_WIDTH = Math.max(ABSOLUTE_MIN_WIDTH, Math.round(workAreaWidth * 0.3));
      MIN_HEIGHT = Math.max(ABSOLUTE_MIN_HEIGHT, Math.round(workAreaHeight * 0.3));

      console.log(`设置最小窗口尺寸: ${MIN_WIDTH}x${MIN_HEIGHT}`);
    } catch (error) {
      console.error('初始化最小窗口尺寸失败:', error);
      // 使用默认值
      MIN_WIDTH = ABSOLUTE_MIN_WIDTH;
      MIN_HEIGHT = ABSOLUTE_MIN_HEIGHT;
    }
  }

  /**
   * 设置事件监听器
   */
  private setupEventListeners(win: BrowserWindow): void {
    // 监听窗口大小调整事件（防抖，拖动结束后统一落盘）
    win.on('resize', () => {
      if (!win.isDestroyed() && !win.isMinimized()) {
        this.scheduleSaveWindowState(win);
      }
    });

    // 监听窗口移动事件（防抖，拖动结束后统一落盘）
    win.on('move', () => {
      if (!win.isDestroyed() && !win.isMinimized()) {
        this.scheduleSaveWindowState(win);
      }
    });

    // 监听窗口最大化事件
    win.on('maximize', () => {
      if (!win.isDestroyed()) {
        this.saveWindowState(win);
      }
    });

    // 监听窗口从最大化恢复事件
    win.on('unmaximize', () => {
      if (!win.isDestroyed()) {
        this.saveWindowState(win);
      }
    });

    // 监听窗口关闭事件，确保保存最终状态（取消挂起的防抖，立即落盘）
    win.on('close', () => {
      this.flushScheduledSave();
      if (!win.isDestroyed()) {
        this.saveWindowState(win);
      }
    });

    // 在页面加载完成后确保窗口大小正确
    win.webContents.on('did-finish-load', () => {
      this.enforceCorrectSize(win);
    });

    // 在窗口准备好显示时确保尺寸正确
    win.on('ready-to-show', () => {
      this.enforceCorrectSize(win);
    });
  }

  /**
   * 强制应用正确的窗口大小
   */
  private enforceCorrectSize(win: BrowserWindow): void {
    if (!this.savedState || win.isMaximized() || win.isMinimized() || win.isDestroyed()) {
      return;
    }

    const [currentWidth, currentHeight] = win.getSize();

    if (
      Math.abs(currentWidth - this.savedState.width) > 2 ||
      Math.abs(currentHeight - this.savedState.height) > 2
    ) {
      console.log(
        `强制调整窗口大小: 当前=${currentWidth}x${currentHeight}, 目标=${this.savedState.width}x${this.savedState.height}`
      );

      // 临时禁用minimum size限制
      const [minWidth, minHeight] = win.getMinimumSize();
      win.setMinimumSize(1, 1);

      // 强制设置正确大小
      win.setSize(this.savedState.width, this.savedState.height, false);

      // 恢复原始minimum size
      win.setMinimumSize(minWidth, minHeight);

      // 验证尺寸设置是否成功
      const [newWidth, newHeight] = win.getSize();
      console.log(`调整后窗口大小: ${newWidth}x${newHeight}`);

      // 如果调整后的大小仍然与目标不一致，尝试再次调整
      if (
        Math.abs(newWidth - this.savedState.width) > 1 ||
        Math.abs(newHeight - this.savedState.height) > 1
      ) {
        console.log(`窗口大小调整后仍不一致，将再次尝试调整`);
        setTimeout(() => {
          if (!win.isDestroyed() && !win.isMaximized() && !win.isMinimized()) {
            win.setSize(this.savedState!.width, this.savedState!.height, false);
          }
        }, 50);
      }

      // // 开始尺寸强制执行
      // this.startSizeEnforcement(win);
    }
  }

  /**
   * 开启尺寸强制执行定时器
   */
  // private startSizeEnforcement(win: BrowserWindow): void {
  //   // 清除之前的定时器
  //   if (this.enforceTimer) {
  //     clearInterval(this.enforceTimer);
  //     this.enforceTimer = null;
  //   }

  //   this.enforceCount = 0;

  //   // 创建新的定时器，每50ms检查一次窗口大小
  //   this.enforceTimer = setInterval(() => {
  //     if (this.enforceCount >= this.MAX_ENFORCE_COUNT ||
  //         !this.savedState ||
  //         win.isDestroyed() ||
  //         win.isMaximized() ||
  //         win.isMinimized()) {
  //       // 达到最大检查次数或不需要检查，清除定时器
  //       if (this.enforceTimer) {
  //         clearInterval(this.enforceTimer);
  //         this.enforceTimer = null;
  //       }
  //       return;
  //     }

  //     const [currentWidth, currentHeight] = win.getSize();

  //     if (Math.abs(currentWidth - this.savedState.width) > 2 ||
  //         Math.abs(currentHeight - this.savedState.height) > 2) {
  //       console.log(`[定时检查] 强制调整窗口大小: 当前=${currentWidth}x${currentHeight}, 目标=${this.savedState.width}x${this.savedState.height}`);

  //       // 临时禁用minimum size限制
  //       const [minWidth, minHeight] = win.getMinimumSize();
  //       win.setMinimumSize(1, 1);

  //       // 强制设置正确大小
  //       win.setSize(this.savedState.width, this.savedState.height, false);

  //       // 恢复原始minimum size
  //       win.setMinimumSize(minWidth, minHeight);

  //       // 验证尺寸设置是否成功
  //       const [newWidth, newHeight] = win.getSize();
  //       if (Math.abs(newWidth - this.savedState.width) <= 1 &&
  //           Math.abs(newHeight - this.savedState.height) <= 1) {
  //         console.log(`窗口大小已成功调整为目标尺寸: ${newWidth}x${newHeight}`);
  //       }
  //     }

  //     this.enforceCount++;
  //   }, 50);
  // }

  /**
   * 获取窗口创建选项
   */
  getWindowOptions(): Electron.BrowserWindowConstructorOptions {
    // 确保初始化
    if (!this.isInitialized && app.isReady()) {
      this.initialize();
    }

    // 读取保存的状态
    const savedState = this.getWindowState();

    // 准备选项
    const options: Electron.BrowserWindowConstructorOptions = {
      width: savedState?.width || DEFAULT_MAIN_WIDTH,
      height: savedState?.height || DEFAULT_MAIN_HEIGHT,
      minWidth: MIN_WIDTH,
      minHeight: MIN_HEIGHT,
      show: false,
      frame: false,
      webPreferences: {
        nodeIntegration: false,
        contextIsolation: true
      }
    };

    // 如果有保存的位置，且位置有效，则使用该位置
    if (savedState?.x !== undefined && savedState?.y !== undefined && app.isReady()) {
      if (this.isPositionVisible(savedState.x, savedState.y)) {
        options.x = savedState.x;
        options.y = savedState.y;
      }
    }

    console.log(
      `窗口创建选项: 大小=${options.width}x${options.height}, 位置=(${options.x}, ${options.y})`
    );

    return options;
  }

  /**
   * 应用窗口初始状态
   * 在窗口创建后调用
   */
  applyInitialState(win: BrowserWindow): void {
    const savedState = this.getWindowState();

    if (!savedState) {
      win.center();
      return;
    }

    // 如果需要最大化，直接最大化
    if (savedState.isMaximized) {
      console.log('应用已保存的最大化状态');
      win.maximize();
    }
    // 如果位置无效，则居中显示
    else if (
      !app.isReady() ||
      savedState.x === undefined ||
      savedState.y === undefined ||
      !this.isPositionVisible(savedState.x, savedState.y)
    ) {
      console.log('保存的位置无效，窗口居中显示');
      win.center();
    }
  }

  /**
   * 保存窗口状态
   */
  saveWindowState(win: BrowserWindow): WindowState {
    // 如果窗口已销毁，则返回之前的状态或默认状态
    if (win.isDestroyed()) {
      return (
        this.savedState || {
          width: DEFAULT_MAIN_WIDTH,
          height: DEFAULT_MAIN_HEIGHT,
          isMaximized: false
        }
      );
    }

    // 检查是否是mini模式窗口（根据窗口大小判断）
    const [currentWidth, currentHeight] = win.getSize();
    const isMiniMode = currentWidth === DEFAULT_MINI_WIDTH && currentHeight === DEFAULT_MINI_HEIGHT;

    const isMaximized = win.isMaximized();
    let state: WindowState;

    if (isMaximized) {
      // 如果窗口处于最大化状态，保存最大化标志
      // 由于 Electron 的限制，最大化状态下 getBounds() 可能不准确
      // 所以我们尽量保留之前保存的非最大化时的大小
      const currentBounds = win.getBounds();
      const previousSize =
        this.savedState && !this.savedState.isMaximized
          ? { width: this.savedState.width, height: this.savedState.height }
          : { width: currentBounds.width, height: currentBounds.height };

      state = {
        width: previousSize.width,
        height: previousSize.height,
        x: currentBounds.x,
        y: currentBounds.y,
        isMaximized: true
      };
      console.log('state IsMaximized', state);
    } else if (win.isMinimized()) {
      // 最小化状态下不保存窗口大小，因为可能不准确
      console.log('state IsMinimized', this.savedState);
      return (
        this.savedState || {
          width: DEFAULT_MAIN_WIDTH,
          height: DEFAULT_MAIN_HEIGHT,
          isMaximized: false
        }
      );
    } else {
      // 正常状态下保存当前大小和位置
      const [width, height] = win.getSize();
      const [x, y] = win.getPosition();

      state = {
        width,
        height,
        x,
        y,
        isMaximized: false
      };
      console.log('state IsNormal', state);
    }

    // 如果是mini模式，不保存到持久化存储，只返回状态用于内存中的恢复
    if (isMiniMode) {
      console.log('检测到mini模式窗口，不保存到持久化存储');
      return state;
    }

    // 保存状态到存储（config.json 可能被外部程序短暂锁定，失败时丢弃本次写入即可）
    try {
      this.store.set(WINDOW_STATE_KEY, state);
      console.log(`已保存窗口状态: ${JSON.stringify(state)}`);
    } catch (error) {
      console.error('保存窗口状态失败:', error);
    }

    // 更新内部状态
    this.savedState = state;
    console.log('state', state);

    return state;
  }

  /**
   * 获取保存的窗口状态
   */
  getWindowState(): WindowState | null {
    let state: WindowState | undefined;
    try {
      state = this.store.get(WINDOW_STATE_KEY) as WindowState | undefined;
    } catch (error) {
      console.error('读取窗口状态失败:', error);
      return this.savedState;
    }

    if (!state) {
      console.log('未找到保存的窗口状态，将使用默认值');
      return null;
    }

    // 验证尺寸，确保不小于最小值
    const validatedState: WindowState = {
      width: Math.max(MIN_WIDTH, state.width || DEFAULT_MAIN_WIDTH),
      height: Math.max(MIN_HEIGHT, state.height || DEFAULT_MAIN_HEIGHT),
      x: state.x,
      y: state.y,
      isMaximized: !!state.isMaximized
    };

    console.log(`读取保存的窗口状态: ${JSON.stringify(validatedState)}`);

    return validatedState;
  }

  /**
   * 检查位置是否在可见屏幕范围内
   */
  isPositionVisible(x: number, y: number): boolean {
    if (!app.isReady()) {
      return false;
    }

    try {
      const displays = screen.getAllDisplays();

      for (const display of displays) {
        const { x: screenX, y: screenY, width, height } = display.workArea;
        if (x >= screenX && x < screenX + width && y >= screenY && y < screenY + height) {
          return true;
        }
      }
    } catch (error) {
      console.error('检查位置可见性失败:', error);
      return false;
    }

    return false;
  }

  /**
   * 计算适合当前缩放比的缩放因子
   */
  calculateContentZoomFactor(): number {
    // 只有在 app 准备好后才能使用screen
    if (!app.isReady()) {
      return 1;
    }

    try {
      // 获取系统的缩放因子
      const { scaleFactor } = screen.getPrimaryDisplay();

      // 缩放因子默认为1
      let zoomFactor = 1;

      // 只在高DPI情况下调整
      if (scaleFactor > 1) {
        // 自定义逻辑来根据不同的缩放比例进行调整
        if (scaleFactor >= 2.5) {
          // 极高缩放比，例如4K屏幕用200%+缩放
          zoomFactor = 0.7;
        } else if (scaleFactor >= 2) {
          // 高缩放比，例如200%
          zoomFactor = 0.8;
        } else if (scaleFactor >= 1.5) {
          // 中等缩放比，例如150%
          zoomFactor = 0.85;
        } else if (scaleFactor > 1.25) {
          // 略高缩放比，例如125%-149%
          zoomFactor = 0.9;
        } else {
          // 低缩放比，不做调整
          zoomFactor = 1;
        }
      }

      // 获取用户的自定义缩放设置（如果有）
      const userZoomFactor = this.store.get('set.contentZoomFactor') as number | undefined;
      if (userZoomFactor) {
        zoomFactor = userZoomFactor;
      }

      return zoomFactor;
    } catch (error) {
      console.error('计算内容缩放因子失败:', error);
      return 1;
    }
  }

  /**
   * 应用页面内容缩放
   */
  applyContentZoom(win: BrowserWindow): void {
    const zoomFactor = this.calculateContentZoomFactor();
    win.webContents.setZoomFactor(zoomFactor);

    if (app.isReady()) {
      try {
        console.log(
          `应用页面缩放因子: ${zoomFactor}, 系统缩放比: ${screen.getPrimaryDisplay().scaleFactor}`
        );
      } catch (error) {
        console.error('获取系统缩放比失败:', error);
      }
    } else {
      console.log(`应用页面缩放因子: ${zoomFactor}`);
    }
  }

  /**
   * 初始化IPC消息处理程序
   */
  setupIPCHandlers(): void {
    // 防止重复注册IPC处理程序
    if (ipcHandlersRegistered) {
      console.log('IPC处理程序已注册，跳过重复注册');
      return;
    }

    console.log('注册窗口大小相关的IPC处理程序');

    // 标记为已注册
    ipcHandlersRegistered = true;

    // 安全地移除已存在的处理程序（如果有）
    const removeHandlerSafely = (channel: string) => {
      try {
        ipcMain.removeHandler(channel);
      } catch (error) {
        console.warn(`移除IPC处理程序 ${channel} 时出错:`, error);
      }
    };

    // 为需要使用handle方法的通道先移除已有处理程序
    removeHandlerSafely('get-content-zoom');
    removeHandlerSafely('get-system-scale-factor');

    // 注册新的处理程序
    ipcMain.on('set-content-zoom', (event, zoomFactor) => {
      const win = BrowserWindow.fromWebContents(event.sender);
      if (win && !win.isDestroyed()) {
        win.webContents.setZoomFactor(zoomFactor);
        this.store.set('set.contentZoomFactor', zoomFactor);
      }
    });

    ipcMain.handle('get-content-zoom', (event) => {
      const win = BrowserWindow.fromWebContents(event.sender);
      if (win && !win.isDestroyed()) {
        return win.webContents.getZoomFactor();
      }
      return 1;
    });

    ipcMain.handle('get-system-scale-factor', () => {
      if (!app.isReady()) {
        return 1;
      }

      try {
        return screen.getPrimaryDisplay().scaleFactor;
      } catch (error) {
        console.error('获取系统缩放因子失败:', error);
        return 1;
      }
    });

    ipcMain.on('reset-content-zoom', (event) => {
      const win = BrowserWindow.fromWebContents(event.sender);
      if (win && !win.isDestroyed()) {
        this.store.delete('set.contentZoomFactor');
        this.applyContentZoom(win);
      }
    });

    ipcMain.on('resize-window', (event, width, height) => {
      const win = BrowserWindow.fromWebContents(event.sender);
      if (win && !win.isDestroyed()) {
        console.log(`接收到调整窗口大小请求: ${width}x${height}`);

        // 确保尺寸不小于最小值
        const adjustedWidth = Math.max(width, MIN_WIDTH);
        const adjustedHeight = Math.max(height, MIN_HEIGHT);

        // 设置窗口的大小
        win.setSize(adjustedWidth, adjustedHeight);
        console.log(`窗口大小已调整为: ${adjustedWidth}x${adjustedHeight}`);

        // 保存窗口状态
        this.saveWindowState(win);
      }
    });

    ipcMain.on('resize-mini-window', (event, showPlaylist) => {
      const win = BrowserWindow.fromWebContents(event.sender);
      if (win && !win.isDestroyed()) {
        if (showPlaylist) {
          console.log(`扩大迷你窗口至 ${DEFAULT_MINI_WIDTH} x ${DEFAULT_MINI_EXPANDED_HEIGHT}`);
          win.setMinimumSize(DEFAULT_MINI_WIDTH, DEFAULT_MINI_HEIGHT);
          win.setMaximumSize(DEFAULT_MINI_WIDTH, DEFAULT_MINI_EXPANDED_HEIGHT);
          win.setSize(DEFAULT_MINI_WIDTH, DEFAULT_MINI_EXPANDED_HEIGHT, false);
        } else {
          console.log(`缩小迷你窗口至 ${DEFAULT_MINI_WIDTH} x ${DEFAULT_MINI_HEIGHT}`);
          win.setMaximumSize(DEFAULT_MINI_WIDTH, DEFAULT_MINI_HEIGHT);
          win.setMinimumSize(DEFAULT_MINI_WIDTH, DEFAULT_MINI_HEIGHT);
          win.setSize(DEFAULT_MINI_WIDTH, DEFAULT_MINI_HEIGHT, false);
        }
      }
    });

    // 只在app ready后设置显示器变化监听
    if (app.isReady()) {
      // 监听显示器变化事件
      screen.on('display-metrics-changed', (_event, _display, changedMetrics) => {
        if (this.mainWindow && !this.mainWindow.isDestroyed()) {
          // 当缩放因子变化时，重新应用页面缩放
          if (changedMetrics.includes('scaleFactor')) {
            this.applyContentZoom(this.mainWindow);
          }

          // 重新初始化最小尺寸
          this.initMinimumWindowSize();
        }
      });
    }

    // 监听 store 中的缩放设置变化
    this.store.onDidChange('set.contentZoomFactor', () => {
      if (this.mainWindow && !this.mainWindow.isDestroyed()) {
        this.applyContentZoom(this.mainWindow);
      }
    });
  }
}

// 创建窗口大小管理器实例
const windowSizeManager = new WindowSizeManager();

// 导出初始化函数
export const initWindowSizeManager = (): void => {
  // 等待app ready后再初始化
  if (app.isReady()) {
    windowSizeManager.initialize();
  } else {
    app.on('ready', () => {
      windowSizeManager.initialize();
    });
  }
};

// 导出实例方法
export const getWindowOptions = (): Electron.BrowserWindowConstructorOptions => {
  return windowSizeManager.getWindowOptions();
};

export const applyInitialState = (win: BrowserWindow): void => {
  windowSizeManager.applyInitialState(win);
};

export const saveWindowState = (win: BrowserWindow): WindowState => {
  return windowSizeManager.saveWindowState(win);
};

export const getWindowState = (): WindowState | null => {
  return windowSizeManager.getWindowState();
};

export const applyContentZoom = (win: BrowserWindow): void => {
  windowSizeManager.applyContentZoom(win);
};

export const initWindowSizeHandlers = (mainWindow: BrowserWindow | null): void => {
  // 确保app ready后再初始化
  if (!app.isReady()) {
    app.on('ready', () => {
      if (mainWindow) {
        windowSizeManager.setMainWindow(mainWindow);
      }
    });
  } else {
    if (mainWindow) {
      windowSizeManager.setMainWindow(mainWindow);
    }
  }
};

export const calculateMinimumWindowSize = (): { minWidth: number; minHeight: number } => {
  return { minWidth: MIN_WIDTH, minHeight: MIN_HEIGHT };
};
