import { app, screen, type BrowserWindow, type Rectangle } from 'electron'
import { join } from 'path'
import { readFileSync, writeFileSync } from 'fs'
import { logger } from './logger'

/**
 * Persist and restore the main window's size / position / maximized state across
 * launches (W2 / UX19) — Windows apps are expected to reopen where you left them.
 * Stored as one small JSON object in `<userData>/window-state.json`; a disconnected
 * monitor is handled by a visibility check so the window can never restore off-screen.
 */

interface WindowState {
  bounds: Rectangle
  maximized: boolean
}

// Matches the createWindow() defaults; used on first run and when a saved position
// is no longer on any connected display.
const DEFAULT_SIZE = { width: 920, height: 700 }

function stateFile(): string {
  return join(app.getPath('userData'), 'window-state.json')
}

function readState(): WindowState | null {
  try {
    const s = JSON.parse(readFileSync(stateFile(), 'utf8')) as Partial<WindowState>
    if (s?.bounds && typeof s.bounds.width === 'number' && typeof s.bounds.height === 'number') {
      return { bounds: s.bounds as Rectangle, maximized: !!s.maximized }
    }
  } catch {
    /* first run or corrupt — fall back to defaults */
  }
  return null
}

/** True when `b` overlaps the work area of some connected display (i.e. is reachable). */
function isOnSomeDisplay(b: Rectangle): boolean {
  return screen.getAllDisplays().some((d) => {
    const wa = d.workArea
    return (
      b.x < wa.x + wa.width &&
      b.x + b.width > wa.x &&
      b.y < wa.y + wa.height &&
      b.y + b.height > wa.y
    )
  })
}

/**
 * The bounds + maximized flag to open the window with. Returns just a size (Electron
 * then centers it) when there's no usable saved position — first run, or the saved
 * monitor is gone.
 */
export function initialWindowState(): {
  width: number
  height: number
  x?: number
  y?: number
  maximized: boolean
} {
  const saved = readState()
  if (saved && isOnSomeDisplay(saved.bounds)) {
    return { ...saved.bounds, maximized: saved.maximized }
  }
  return { ...DEFAULT_SIZE, maximized: saved?.maximized ?? false }
}

/**
 * Persist the window's current *normal* bounds (un-maximized) + maximized flag.
 * Best-effort; a write failure is logged, never thrown. Callers should debounce.
 */
export function saveWindowState(win: BrowserWindow): void {
  if (win.isDestroyed() || win.isMinimized()) return
  try {
    const state: WindowState = { bounds: win.getNormalBounds(), maximized: win.isMaximized() }
    writeFileSync(stateFile(), JSON.stringify(state))
  } catch (e) {
    logger.warn('failed to save window state', e)
  }
}
