import { app, shell, type BrowserWindow } from 'electron'
import { existsSync, openSync, readSync, closeSync } from 'fs'
import { join } from 'path'
import { assertHttpUrl } from './url'
import { parseUrlShortcutContent } from '@shared/ipc'

/** Only ever forward http(s) targets into the app — same restriction the
 *  external-link window-open handler in index.ts applies to in-page links.
 *  Delegates to the download path's guard so an incoming deep-link target is
 *  validated AND parser-normalised (no embedded tabs/newlines/control chars
 *  reach the renderer); returns null instead of throwing for the argv scan.
 *  (audit T3 / F5) */
function asHttpUrl(candidate: string): string | null {
  try {
    return assertHttpUrl(candidate)
  } catch {
    return null
  }
}

/** Reads a Windows Internet Shortcut (.url) file's target — what Explorer's
 *  "Send to" menu hands us when the user sends a saved link to AeroFetch.
 *  Only the first 64 KB is read: a real shortcut is a few hundred bytes, so this
 *  caps memory and limits exposure if argv points at a pathological or oversized
 *  file that merely ends in `.url`. (audit T5) */
const MAX_URL_FILE_BYTES = 64 * 1024
function readUrlShortcut(path: string): string | null {
  let fd: number | null = null
  try {
    fd = openSync(path, 'r')
    const buf = Buffer.alloc(MAX_URL_FILE_BYTES)
    const bytes = readSync(fd, buf, 0, buf.length, 0)
    const url = parseUrlShortcutContent(buf.toString('utf8', 0, bytes))
    return url ? asHttpUrl(url) : null
  } catch {
    return null
  } finally {
    if (fd !== null) closeSync(fd)
  }
}

/**
 * Pulls a download target out of process argv — either the `aerofetch://`
 * custom protocol (`aerofetch://download?url=<encoded>`) or a `.url` Internet
 * Shortcut path Explorer's "Send to" menu passes us (see registerSendToShortcut).
 */
export function extractIncomingUrl(argv: string[]): string | null {
  for (const arg of argv) {
    if (/^aerofetch:\/\//i.test(arg)) {
      try {
        const target = new URL(arg).searchParams.get('url')
        const valid = target && asHttpUrl(target)
        if (valid) return valid
      } catch {
        /* malformed protocol invocation — ignore */
      }
    } else if (/\.url$/i.test(arg) && existsSync(arg)) {
      const target = readUrlShortcut(arg)
      if (target) return target
    }
  }
  return null
}

/**
 * Adds/refreshes a "Send to AeroFetch" entry in Explorer's SendTo menu — the
 * closest Windows analog to Android's share sheet a Win32 (non-MSIX) app can
 * offer; registering as an actual Share Target requires an MSIX package.
 * Best-effort and idempotent (re-running just overwrites the same shortcut),
 * so a failure here should never block startup.
 */
export function registerSendToShortcut(): void {
  if (process.platform !== 'win32') return
  try {
    const shortcutPath = join(
      app.getPath('appData'),
      'Microsoft',
      'Windows',
      'SendTo',
      'AeroFetch.lnk'
    )
    shell.writeShortcutLink(shortcutPath, {
      target: process.execPath,
      description: 'Send to AeroFetch',
      icon: process.execPath,
      iconIndex: 0
    })
  } catch {
    /* SendTo integration is a nice-to-have */
  }
}

/** Focuses (and un-minimizes) an existing window — used when a second launch
 *  (protocol or SendTo) should hand its URL to the already-running instance. */
export function focusWindow(win: BrowserWindow): void {
  if (win.isMinimized()) win.restore()
  win.show()
  win.focus()
}
