import { useCallback, useEffect, useMemo, useState, type ReactNode } from 'react'
import {
  MdApps,
  MdDns,
  MdFolderOpen,
  MdMemory,
  MdRefresh,
  MdSchedule,
  MdSettingsApplications,
  MdStorage,
  MdViewModule,
  MdWarning,
  MdOpenInNew,
  MdArrowUpward,
  MdSearch,
  MdNoteAdd,
  MdDeleteForever,
  MdSave,
  MdStopCircle,
  MdComputer,
  MdCode,
  MdContentCopy,
  MdDataUsage,
} from 'react-icons/md'
import { IconButton } from './components/IconButton'
import { formatBytes, formatSizeKb, formatUptime } from './utils/format'
import type {
  DirEntry,
  DriveInfo,
  InstalledApp,
  NavId,
  NetworkRow,
  ProcessRow,
  ServiceRow,
  SystemSnapshot,
} from './types'

const api = typeof window !== 'undefined' ? window.auditor : undefined

function useNotes() {
  const [map, setMap] = useState<Record<string, string>>({})
  const refresh = useCallback(async () => {
    if (!api) return
    setMap(await api.notesGetAll())
  }, [])
  useEffect(() => {
    void refresh()
  }, [refresh])
  const setNote = useCallback(
    async (key: string, value: string) => {
      if (!api) return
      setMap(await api.notesSet(key, value))
    },
    []
  )
  const del = useCallback(
    async (key: string) => {
      if (!api) return
      setMap(await api.notesDelete(key))
    },
    []
  )
  return { map, refresh, setNote, del }
}

const NAV: { id: NavId; label: string; icon: ReactNode }[] = [
  { id: 'overview', label: 'Overview', icon: <MdViewModule /> },
  { id: 'storage', label: 'Storage & volumes', icon: <MdStorage /> },
  { id: 'filesystem', label: 'Folders & files', icon: <MdFolderOpen /> },
  { id: 'processes', label: 'Processes', icon: <MdMemory /> },
  { id: 'services', label: 'Services', icon: <MdSettingsApplications /> },
  { id: 'apps', label: 'Installed software', icon: <MdApps /> },
  { id: 'network', label: 'Network', icon: <MdDns /> },
  { id: 'environment', label: 'Environment', icon: <MdCode /> },
  { id: 'startup', label: 'Startup items', icon: <MdComputer /> },
  { id: 'scheduled', label: 'Scheduled tasks', icon: <MdSchedule /> },
  { id: 'features', label: 'Windows features', icon: <MdWarning /> },
]

export default function App() {
  const [nav, setNav] = useState<NavId>('overview')
  const [status, setStatus] = useState('')
  const [err, setErr] = useState('')
  const notes = useNotes()

  const [sys, setSys] = useState<SystemSnapshot | null>(null)
  const [drives, setDrives] = useState<DriveInfo[]>([])
  const [path, setPath] = useState('')
  const [entries, setEntries] = useState<DirEntry[]>([])
  const [proc, setProc] = useState<ProcessRow[]>([])
  const [svc, setSvc] = useState<ServiceRow[]>([])
  const [apps, setApps] = useState<InstalledApp[]>([])
  const [net, setNet] = useState<NetworkRow[]>([])
  const [envText, setEnvText] = useState('')
  const [startupBlocks, setStartupBlocks] = useState<{ path: string; entries: DirEntry[] }[]>([])
  const [tasks, setTasks] = useState<{ name: string; state: string }[]>([])
  const [feat, setFeat] = useState('')
  const [tempAudit, setTempAudit] = useState<{ path: string; bytes: number; files: number; truncated: boolean }[]>(
    []
  )

  const [selectedKey, setSelectedKey] = useState<string | null>(null)
  const [noteDraft, setNoteDraft] = useState('')

  const [largeRoot, setLargeRoot] = useState('')
  const [largeMinMb, setLargeMinMb] = useState(100)
  const [largeHits, setLargeHits] = useState<{ path: string; sizeBytes: number }[]>([])
  const [folderTotal, setFolderTotal] = useState<{
    bytes: number
    files: number
    truncated: boolean
  } | null>(null)

  const [procFilter, setProcFilter] = useState('')
  const [svcFilter, setSvcFilter] = useState('')
  const [appFilter, setAppFilter] = useState('')

  const clearMsg = () => {
    setErr('')
    setStatus('')
  }

  const loadSystem = useCallback(async (opts?: { silent?: boolean }) => {
    if (!api) return
    if (!opts?.silent) clearMsg()
    try {
      setSys((await api.system()) as SystemSnapshot)
      if (!opts?.silent) setStatus('System snapshot updated')
    } catch (e) {
      if (!opts?.silent) setErr(String((e as Error).message))
    }
  }, [])

  const loadDrives = useCallback(async () => {
    if (!api) return
    clearMsg()
    try {
      setDrives((await api.drives()) as DriveInfo[])
      setStatus('Volumes refreshed')
    } catch (e) {
      setErr(String((e as Error).message))
    }
  }, [])

  const loadDir = useCallback(async () => {
    if (!api || !path.trim()) return
    clearMsg()
    try {
      setStatus('Listing folder (measuring sizes)…')
      setEntries((await api.listDir(path.trim(), { maxEntries: 800 })) as DirEntry[])
      setStatus('Directory listed')
    } catch (e) {
      setErr(String((e as Error).message))
    }
  }, [path])

  const loadProcesses = useCallback(async () => {
    if (!api) return
    clearMsg()
    setStatus('Loading processes…')
    try {
      const rows = (await api.processes()) as ProcessRow[]
      setProc(rows)
      setStatus(`Processes loaded (${rows.length})`)
    } catch (e) {
      setErr(String((e as Error).message))
    }
  }, [])

  const loadServices = useCallback(async () => {
    if (!api) return
    clearMsg()
    setStatus('Loading services…')
    try {
      setSvc((await api.services()) as ServiceRow[])
      setStatus('Services loaded')
    } catch (e) {
      setErr(String((e as Error).message))
    }
  }, [])

  const loadApps = useCallback(async () => {
    if (!api) return
    clearMsg()
    try {
      setApps((await api.installed()) as InstalledApp[])
      setStatus('Installed programs enumerated')
    } catch (e) {
      setErr(String((e as Error).message))
    }
  }, [])

  const loadNetwork = useCallback(async () => {
    if (!api) return
    clearMsg()
    try {
      setNet((await api.network()) as NetworkRow[])
      setStatus('Network interfaces read')
    } catch (e) {
      setErr(String((e as Error).message))
    }
  }, [])

  const loadEnv = useCallback(async () => {
    if (!api) return
    clearMsg()
    try {
      const o = (await api.env()) as Record<string, string>
      const lines = Object.keys(o)
        .sort()
        .map((k) => `${k}=${o[k]}`)
      setEnvText(lines.join('\n'))
      setStatus('Environment loaded')
    } catch (e) {
      setErr(String((e as Error).message))
    }
  }, [])

  const loadStartup = useCallback(async () => {
    if (!api) return
    clearMsg()
    try {
      setStartupBlocks((await api.startup()) as { path: string; entries: DirEntry[] }[])
      setStatus('Startup folders scanned')
    } catch (e) {
      setErr(String((e as Error).message))
    }
  }, [])

  const loadTasks = useCallback(async () => {
    if (!api) return
    clearMsg()
    setStatus('Loading scheduled tasks…')
    try {
      setTasks((await api.tasks()) as { name: string; state: string }[])
      setStatus('Scheduled tasks loaded')
    } catch (e) {
      setErr(String((e as Error).message))
    }
  }, [])

  const loadFeatures = useCallback(async () => {
    if (!api) return
    clearMsg()
    setStatus('Querying optional features (may take a minute)…')
    try {
      setFeat(await api.features())
      setStatus('Feature list retrieved')
    } catch (e) {
      setErr(String((e as Error).message))
    }
  }, [])

  const loadTemp = useCallback(async () => {
    if (!api) return
    clearMsg()
    setStatus('Measuring temp folders…')
    try {
      setTempAudit(
        (await api.temp()) as { path: string; bytes: number; files: number; truncated: boolean }[]
      )
      setStatus('Temp audit complete')
    } catch (e) {
      setErr(String((e as Error).message))
    }
  }, [])

  useEffect(() => {
    if (!api) return
    void loadSystem()
    const t = setInterval(() => void loadSystem({ silent: true }), 60_000)
    return () => clearInterval(t)
  }, [loadSystem])

  const [pathSeeded, setPathSeeded] = useState(false)
  useEffect(() => {
    if (!api || pathSeeded) return
    if (sys?.homedir) {
      setPath(sys.homedir)
      setPathSeeded(true)
    }
  }, [api, sys, pathSeeded])

  useEffect(() => {
    if (selectedKey && notes.map[selectedKey] !== undefined) setNoteDraft(notes.map[selectedKey] ?? '')
    else if (selectedKey) setNoteDraft('')
  }, [selectedKey, notes.map])

  const selectForNote = (key: string) => {
    setSelectedKey(key)
    setNoteDraft(notes.map[key] ?? '')
  }

  const saveNote = async () => {
    if (!selectedKey) return
    await notes.setNote(selectedKey, noteDraft)
    setStatus('Note saved')
  }

  const copyText = async (text: string) => {
    if (!api) return
    try {
      if (navigator.clipboard?.writeText) {
        await navigator.clipboard.writeText(text)
      } else {
        await api.clipboardWriteText(text)
      }
      setStatus('Copied to clipboard')
    } catch {
      try {
        await api.clipboardWriteText(text)
        setStatus('Copied to clipboard')
      } catch (e) {
        setErr(String((e as Error).message))
      }
    }
  }

  const computeFolderTotal = async () => {
    if (!api || !path.trim()) return
    clearMsg()
    setStatus('Computing folder size (capped walk)…')
    try {
      const r = (await api.folderSize(path.trim())) as { bytes: number; files: number; truncated: boolean }
      setFolderTotal(r)
      setStatus(
        `Folder total ${formatSizeKb(r.bytes, { truncated: r.truncated })} — ${r.files} files counted${r.truncated ? ' (hit file cap)' : ''}`
      )
    } catch (e) {
      setErr(String((e as Error).message))
    }
  }

  const runLargeScan = async () => {
    if (!api) return
    const root = largeRoot.trim() || path.trim()
    if (!root) return
    clearMsg()
    setStatus('Scanning for large files…')
    try {
      const hits = (await api.largeFiles(root, largeMinMb * 1024 * 1024, 80)) as {
        path: string
        sizeBytes: number
      }[]
      setLargeHits(hits)
      setStatus(`Found ${hits.length} files`)
    } catch (e) {
      setErr(String((e as Error).message))
    }
  }

  const killPid = async (pid: number) => {
    if (!api) return
    if (!window.confirm(`End process ${pid}? Unsaved data in that process may be lost.`)) return
    try {
      await api.killProcess(pid)
      setStatus(`Sent terminate to PID ${pid}`)
      void loadProcesses()
    } catch (e) {
      setErr(String((e as Error).message))
    }
  }

  const openExplorer = async (p: string) => {
    if (!api) return
    try {
      await api.openExplorer(p)
    } catch (e) {
      setErr(String((e as Error).message))
    }
  }

  const filteredProc = useMemo(() => {
    const q = procFilter.trim().toLowerCase()
    if (!q) return proc
    return proc.filter(
      (p) =>
        p.name.toLowerCase().includes(q) ||
        String(p.pid).includes(q) ||
        (p.commandLine ?? '').toLowerCase().includes(q)
    )
  }, [proc, procFilter])

  const filteredSvc = useMemo(() => {
    const q = svcFilter.trim().toLowerCase()
    if (!q) return svc
    return svc.filter(
      (s) =>
        s.name.toLowerCase().includes(q) ||
        s.displayName.toLowerCase().includes(q) ||
        s.state.toLowerCase().includes(q)
    )
  }, [svc, svcFilter])

  const filteredApps = useMemo(() => {
    const q = appFilter.trim().toLowerCase()
    if (!q) return apps
    return apps.filter(
      (a) =>
        a.name.toLowerCase().includes(q) ||
        a.publisher.toLowerCase().includes(q) ||
        a.installLocation.toLowerCase().includes(q)
    )
  }, [apps, appFilter])

  if (!api) {
    return (
      <div className="content-scroll">
        <p className="status-msg error">
          This UI must be run inside the Electron shell so it can reach your system. Use{' '}
          <span className="mono">npm run dev</span>.
        </p>
      </div>
    )
  }

  const memUsed = sys ? sys.totalMem - sys.freeMem : 0
  const memPct = sys && sys.totalMem ? Math.round((memUsed / sys.totalMem) * 100) : 0

  return (
    <div className="app-shell">
      <aside className="sidebar">
        <div className="sidebar-brand">
          <h1>Computer Auditor</h1>
          <p>System inspection dashboard</p>
        </div>
        {NAV.map((item) => (
          <button
            key={item.id}
            type="button"
            className={`nav-item ${nav === item.id ? 'active' : ''}`}
            onClick={() => setNav(item.id)}
          >
            {item.icon}
            {item.label}
          </button>
        ))}
      </aside>

      <div className="main">
        <div className="toolbar">
          <h2 className="panel-title">{NAV.find((n) => n.id === nav)?.label}</h2>
          <span className="toolbar-spacer" />
          <IconButton label="Refresh system snapshot" onClick={() => void loadSystem()}>
            <MdRefresh />
          </IconButton>
          {status && <span className="status-msg">{status}</span>}
          {err && <span className="status-msg error">{err}</span>}
        </div>

        <div className="content-scroll">
          {nav === 'overview' && (
            <>
              <div className="card-grid">
                <div className="card">
                  <div className="card-label">Host</div>
                  <div className="card-value">{sys?.hostname ?? '—'}</div>
                  <div className="card-sub mono">{sys?.userInfo}</div>
                </div>
                <div className="card">
                  <div className="card-label">Platform</div>
                  <div className="card-value">{sys?.platform ?? '—'}</div>
                  <div className="card-sub mono">
                    {sys?.release} / {sys?.arch}
                  </div>
                </div>
                <div className="card">
                  <div className="card-label">Uptime</div>
                  <div className="card-value">{sys ? formatUptime(sys.uptimeSec) : '—'}</div>
                </div>
                <div className="card">
                  <div className="card-label">Memory</div>
                  <div className="card-value">
                    {sys ? `${memPct}% used` : '—'}
                  </div>
                  <div className="card-sub">
                    {sys ? `${formatBytes(memUsed)} / ${formatBytes(sys.totalMem)}` : ''}
                  </div>
                  {sys && (
                    <div className="bar-track">
                      <div className="bar-fill" style={{ width: `${memPct}%` }} />
                    </div>
                  )}
                </div>
                <div className="card">
                  <div className="card-label">CPU</div>
                  <div className="card-value">{sys?.cpuCount ?? '—'} logical</div>
                  <div className="card-sub">{sys?.cpuModel}</div>
                </div>
                <div className="card">
                  <div className="card-label">Home & temp</div>
                  <div className="card-sub mono">{sys?.homedir}</div>
                  <div className="card-sub mono">{sys?.tmpdir}</div>
                </div>
              </div>

              <div style={{ marginTop: 20 }}>
                <div className="input-row">
                  <IconButton label="Load logical volumes" onClick={() => void loadDrives()}>
                    <MdStorage />
                  </IconButton>
                  <IconButton label="Measure temp directories" onClick={() => void loadTemp()}>
                    <MdFolderOpen />
                  </IconButton>
                </div>
                {drives.length > 0 && (
                  <table className="data-table">
                    <thead>
                      <tr>
                        <th>Volume</th>
                        <th>Label</th>
                        <th>Used</th>
                        <th>Free</th>
                        <th>Total</th>
                        <th />
                      </tr>
                    </thead>
                    <tbody>
                      {drives.map((d) => {
                        const pct = d.totalBytes ? Math.round((d.usedBytes / d.totalBytes) * 100) : 0
                        return (
                          <tr key={d.letter}>
                            <td className="mono">{d.letter}</td>
                            <td>{d.label || '—'}</td>
                            <td>
                              {formatBytes(d.usedBytes)} ({pct}%)
                            </td>
                            <td>{formatBytes(d.freeBytes)}</td>
                            <td>{formatBytes(d.totalBytes)}</td>
                            <td>
                              <IconButton
                                label="Open in Explorer"
                                onClick={() => void openExplorer(d.mount + '\\')}
                              >
                                <MdOpenInNew />
                              </IconButton>
                              <IconButton
                                label="Attach note to this volume"
                                onClick={() => selectForNote(`drive:${d.letter}`)}
                              >
                                <MdNoteAdd />
                              </IconButton>
                            </td>
                          </tr>
                        )
                      })}
                    </tbody>
                  </table>
                )}
                {tempAudit.length > 0 && (
                  <table className="data-table" style={{ marginTop: 16 }}>
                    <thead>
                      <tr>
                        <th>Temp path</th>
                        <th>Size</th>
                        <th>Files (sampled)</th>
                      </tr>
                    </thead>
                    <tbody>
                      {tempAudit.map((t) => (
                        <tr key={t.path}>
                          <td className="mono">{t.path}</td>
                          <td>{formatBytes(t.bytes)}</td>
                          <td>
                            {t.files}
                            {t.truncated ? ' (cap reached)' : ''}
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                )}
              </div>
            </>
          )}

          {nav === 'storage' && (
            <>
              <div className="input-row">
                <IconButton label="Refresh drive list" onClick={() => void loadDrives()}>
                  <MdRefresh />
                </IconButton>
              </div>
              <table className="data-table">
                <thead>
                  <tr>
                    <th>Volume</th>
                    <th>Label</th>
                    <th>Used</th>
                    <th>Free</th>
                    <th>Total</th>
                    <th />
                  </tr>
                </thead>
                <tbody>
                  {drives.map((d) => {
                    const pct = d.totalBytes ? Math.round((d.usedBytes / d.totalBytes) * 100) : 0
                    return (
                      <tr key={d.letter}>
                        <td className="mono">{d.letter}</td>
                        <td>{d.label || '—'}</td>
                        <td>
                          {formatBytes(d.usedBytes)} ({pct}%)
                          <div className="bar-track">
                            <div className="bar-fill" style={{ width: `${pct}%` }} />
                          </div>
                        </td>
                        <td>{formatBytes(d.freeBytes)}</td>
                        <td>{formatBytes(d.totalBytes)}</td>
                        <td>
                          <IconButton label="Open volume" onClick={() => void openExplorer(d.mount + '\\')}>
                            <MdOpenInNew />
                          </IconButton>
                          <IconButton label="Note" onClick={() => selectForNote(`drive:${d.letter}`)}>
                            <MdNoteAdd />
                          </IconButton>
                        </td>
                      </tr>
                    )
                  })}
                </tbody>
              </table>
            </>
          )}

          {nav === 'filesystem' && (
            <>
              <div className="input-row">
                <input
                  type="text"
                  value={path}
                  onChange={(e) => setPath(e.target.value)}
                  placeholder="Folder path"
                  className="mono"
                  style={{ flex: 1, minWidth: 280 }}
                />
                <IconButton label="List directory" onClick={() => void loadDir()}>
                  <MdRefresh />
                </IconButton>
                <IconButton label="Parent folder" onClick={() => setPath((p) => p.replace(/[/\\][^/\\]*$/, ''))}>
                  <MdArrowUpward />
                </IconButton>
                <IconButton label="Open in Explorer" onClick={() => void openExplorer(path)}>
                  <MdOpenInNew />
                </IconButton>
                <IconButton label="Note on this path" onClick={() => selectForNote(`path:${path}`)}>
                  <MdNoteAdd />
                </IconButton>
                <IconButton label="Copy current path" onClick={() => void copyText(path)}>
                  <MdContentCopy />
                </IconButton>
                <IconButton label="Compute folder size (recursive, capped)" onClick={() => void computeFolderTotal()}>
                  <MdDataUsage />
                </IconButton>
              </div>
              {folderTotal && (
                <p className="status-msg" style={{ marginTop: 0 }}>
                  Aggregated: {formatSizeKb(folderTotal.bytes, { truncated: folderTotal.truncated })} —{' '}
                  {folderTotal.files} files
                  {folderTotal.truncated ? ' (enumeration capped for safety)' : ''}
                </p>
              )}
              <div className="input-row">
                <input
                  type="text"
                  value={largeRoot}
                  onChange={(e) => setLargeRoot(e.target.value)}
                  placeholder="Large-file scan root (defaults to path above)"
                  className="mono"
                  style={{ flex: 1, minWidth: 240 }}
                />
                <input
                  type="number"
                  value={largeMinMb}
                  min={1}
                  onChange={(e) => setLargeMinMb(Number(e.target.value) || 100)}
                  title="Minimum size MB"
                />
                <IconButton label="Find large files" onClick={() => void runLargeScan()}>
                  <MdSearch />
                </IconButton>
              </div>
              <table className="data-table">
                <thead>
                  <tr>
                    <th>Name</th>
                    <th>Type</th>
                    <th>Size (KB)</th>
                    <th />
                  </tr>
                </thead>
                <tbody>
                  {entries.map((e) => (
                    <tr
                      key={e.fullPath}
                      className={selectedKey === `path:${e.fullPath}` ? 'selected' : ''}
                      onDoubleClick={() => e.isDirectory && setPath(e.fullPath)}
                    >
                      <td className="mono">{e.name}</td>
                      <td>{e.isDirectory ? 'Folder' : 'File'}</td>
                      <td>
                        {e.error
                          ? e.error
                          : formatSizeKb(e.sizeBytes, { truncated: e.sizeTruncated })}
                      </td>
                      <td>
                        {e.isDirectory && (
                          <IconButton label="Enter folder" onClick={() => setPath(e.fullPath)}>
                            <MdFolderOpen />
                          </IconButton>
                        )}
                        <IconButton label="Explorer" onClick={() => void openExplorer(e.fullPath)}>
                          <MdOpenInNew />
                        </IconButton>
                        <IconButton label="Note" onClick={() => selectForNote(`path:${e.fullPath}`)}>
                          <MdNoteAdd />
                        </IconButton>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
              {largeHits.length > 0 && (
                <>
                  <h3 style={{ marginTop: 24, fontSize: 13 }}>Large files</h3>
                  <table className="data-table">
                    <thead>
                      <tr>
                        <th>Path</th>
                        <th>Size (KB)</th>
                        <th />
                      </tr>
                    </thead>
                    <tbody>
                      {largeHits.map((h) => (
                        <tr key={h.path}>
                          <td className="mono">{h.path}</td>
                          <td>{formatSizeKb(h.sizeBytes)}</td>
                          <td>
                            <IconButton label="Open location" onClick={() => void openExplorer(h.path)}>
                              <MdOpenInNew />
                            </IconButton>
                            <IconButton label="Note" onClick={() => selectForNote(`path:${h.path}`)}>
                              <MdNoteAdd />
                            </IconButton>
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </>
              )}
            </>
          )}

          {nav === 'processes' && (
            <>
              <div className="input-row">
                <IconButton label="Reload process list" onClick={() => void loadProcesses()}>
                  <MdRefresh />
                </IconButton>
                <input
                  type="search"
                  placeholder="Filter name, PID, command line"
                  value={procFilter}
                  onChange={(e) => setProcFilter(e.target.value)}
                  style={{ minWidth: 240, flex: 1 }}
                />
              </div>
              <table className="data-table">
                <thead>
                  <tr>
                    <th>PID</th>
                    <th>Name</th>
                    <th>Memory</th>
                    <th>CPU (session est.)</th>
                    <th />
                  </tr>
                </thead>
                <tbody>
                  {filteredProc.map((p) => (
                    <tr
                      key={p.pid}
                      className={selectedKey === `proc:${p.pid}` ? 'selected' : ''}
                      title={p.commandLine}
                    >
                      <td className="mono">{p.pid}</td>
                      <td>{p.name}</td>
                      <td>{formatBytes(p.memoryBytes)}</td>
                      <td>{p.cpuSeconds != null ? `${p.cpuSeconds}s` : '—'}</td>
                      <td>
                        <IconButton label="Add note for process" onClick={() => selectForNote(`proc:${p.pid}`)}>
                          <MdNoteAdd />
                        </IconButton>
                        <IconButton label="End process" onClick={() => void killPid(p.pid)}>
                          <MdStopCircle />
                        </IconButton>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </>
          )}

          {nav === 'services' && (
            <>
              <div className="input-row">
                <IconButton label="Reload services" onClick={() => void loadServices()}>
                  <MdRefresh />
                </IconButton>
                <input
                  type="search"
                  placeholder="Filter"
                  value={svcFilter}
                  onChange={(e) => setSvcFilter(e.target.value)}
                  style={{ minWidth: 240, flex: 1 }}
                />
              </div>
              <table className="data-table">
                <thead>
                  <tr>
                    <th>Name</th>
                    <th>Display name</th>
                    <th>State</th>
                    <th>Start</th>
                    <th />
                  </tr>
                </thead>
                <tbody>
                  {filteredSvc.map((s) => (
                    <tr key={s.name} className={selectedKey === `svc:${s.name}` ? 'selected' : ''}>
                      <td className="mono">{s.name}</td>
                      <td>{s.displayName}</td>
                      <td>{s.state}</td>
                      <td>{s.startType}</td>
                      <td>
                        <IconButton label="Note" onClick={() => selectForNote(`svc:${s.name}`)}>
                          <MdNoteAdd />
                        </IconButton>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </>
          )}

          {nav === 'apps' && (
            <>
              <div className="input-row">
                <IconButton label="Reload installed programs" onClick={() => void loadApps()}>
                  <MdRefresh />
                </IconButton>
                <input
                  type="search"
                  placeholder="Filter"
                  value={appFilter}
                  onChange={(e) => setAppFilter(e.target.value)}
                  style={{ minWidth: 240, flex: 1 }}
                />
              </div>
              <table className="data-table">
                <thead>
                  <tr>
                    <th>Name</th>
                    <th>Version</th>
                    <th>Publisher</th>
                    <th>Location</th>
                    <th>Est. size</th>
                    <th />
                  </tr>
                </thead>
                <tbody>
                  {filteredApps.map((a) => (
                    <tr
                      key={a.name + a.version}
                      className={selectedKey === `app:${a.name}` ? 'selected' : ''}
                    >
                      <td>{a.name}</td>
                      <td className="mono">{a.version}</td>
                      <td>{a.publisher}</td>
                      <td className="mono">{a.installLocation || '—'}</td>
                      <td>{a.estimatedSizeKb ? `${(a.estimatedSizeKb / 1024).toFixed(1)} MB` : '—'}</td>
                      <td>
                        {a.installLocation ? (
                          <IconButton label="Open install folder" onClick={() => void openExplorer(a.installLocation)}>
                            <MdOpenInNew />
                          </IconButton>
                        ) : null}
                        <IconButton label="Note" onClick={() => selectForNote(`app:${a.name}`)}>
                          <MdNoteAdd />
                        </IconButton>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </>
          )}

          {nav === 'network' && (
            <>
              <div className="input-row">
                <IconButton label="Reload interfaces" onClick={() => void loadNetwork()}>
                  <MdRefresh />
                </IconButton>
              </div>
              <table className="data-table">
                <thead>
                  <tr>
                    <th>Interface</th>
                    <th>Address</th>
                    <th>Family</th>
                    <th>MAC</th>
                    <th>Internal</th>
                    <th />
                  </tr>
                </thead>
                <tbody>
                  {net.map((n, i) => (
                    <tr key={`${n.name}-${n.address}-${i}`}>
                      <td>{n.name}</td>
                      <td className="mono">{n.address}</td>
                      <td>{n.family}</td>
                      <td className="mono">{n.mac ?? '—'}</td>
                      <td>{n.internal ? 'yes' : 'no'}</td>
                      <td>
                        <IconButton label="Note" onClick={() => selectForNote(`net:${n.name}:${n.address}`)}>
                          <MdNoteAdd />
                        </IconButton>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </>
          )}

          {nav === 'environment' && (
            <>
              <div className="input-row">
                <IconButton label="Reload environment block" onClick={() => void loadEnv()}>
                  <MdRefresh />
                </IconButton>
                <IconButton label="Note on whole environment view" onClick={() => selectForNote('env:all')}>
                  <MdNoteAdd />
                </IconButton>
              </div>
              <textarea className="mono" value={envText} readOnly spellCheck={false} style={{ minHeight: 400 }} />
            </>
          )}

          {nav === 'startup' && (
            <>
              <div className="input-row">
                <IconButton label="Scan startup folders" onClick={() => void loadStartup()}>
                  <MdRefresh />
                </IconButton>
              </div>
              {startupBlocks.map((block) => (
                <div key={block.path} style={{ marginBottom: 20 }}>
                  <div className="card-label mono" style={{ marginBottom: 8 }}>
                    {block.path}
                  </div>
                  <table className="data-table">
                    <thead>
                      <tr>
                        <th>Item</th>
                        <th>Type</th>
                        <th />
                      </tr>
                    </thead>
                    <tbody>
                      {block.entries.map((e) => (
                        <tr key={e.fullPath}>
                          <td className="mono">{e.name}</td>
                          <td>{e.isDirectory ? 'Folder' : 'File'}</td>
                          <td>
                            <IconButton label="Open" onClick={() => void openExplorer(e.fullPath)}>
                              <MdOpenInNew />
                            </IconButton>
                            <IconButton label="Note" onClick={() => selectForNote(`path:${e.fullPath}`)}>
                              <MdNoteAdd />
                            </IconButton>
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              ))}
            </>
          )}

          {nav === 'scheduled' && (
            <>
              <div className="input-row">
                <IconButton label="Reload tasks" onClick={() => void loadTasks()}>
                  <MdRefresh />
                </IconButton>
              </div>
              <table className="data-table">
                <thead>
                  <tr>
                    <th>Task</th>
                    <th>State</th>
                    <th />
                  </tr>
                </thead>
                <tbody>
                  {tasks.map((t) => (
                    <tr key={t.name} className={selectedKey === `task:${t.name}` ? 'selected' : ''}>
                      <td className="mono">{t.name}</td>
                      <td>{t.state}</td>
                      <td>
                        <IconButton label="Note" onClick={() => selectForNote(`task:${t.name}`)}>
                          <MdNoteAdd />
                        </IconButton>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </>
          )}

          {nav === 'features' && (
            <>
              <div className="input-row">
                <IconButton label="Load DISM feature table" onClick={() => void loadFeatures()}>
                  <MdRefresh />
                </IconButton>
                <IconButton label="Note on features output" onClick={() => selectForNote('features:snippet')}>
                  <MdNoteAdd />
                </IconButton>
              </div>
              <pre className="features-pre mono">{feat || 'Run refresh to pull optional features snapshot.'}</pre>
            </>
          )}
        </div>

        <footer className="notes-panel">
          <header>
            <strong>Notes</strong>
            <span className="notes-key">{selectedKey ?? 'Select a row or volume to attach a note key.'}</span>
          </header>
          <textarea
            placeholder="Audit notes for the selected item…"
            value={noteDraft}
            onChange={(e) => setNoteDraft(e.target.value)}
            disabled={!selectedKey}
          />
          <div className="input-row" style={{ marginBottom: 0 }}>
            <IconButton label="Save note" onClick={() => void saveNote()} disabled={!selectedKey}>
              <MdSave />
            </IconButton>
            <IconButton
              label="Clear note for key"
              onClick={() => selectedKey && void notes.del(selectedKey)}
              disabled={!selectedKey}
            >
              <MdDeleteForever />
            </IconButton>
            <IconButton label="Reload notes from disk" onClick={() => void notes.refresh()}>
              <MdRefresh />
            </IconButton>
          </div>
        </footer>
      </div>
    </div>
  )
}
