import { isDebugMode } from './env.js'
import { getCurrentHashPath, isPublicPath } from '@/config/security.js'

const DEVTOOLS_WIDTH_THRESHOLD = 160
const SECURITY_REDIRECT = '/#/not_app?message=Please%20open%20this%20page%20inside%20the%20official%20app'

function isEditableElement(target) {
  return Boolean(
    target?.closest?.(
      'input, textarea, select, [contenteditable=""], [contenteditable="true"], [data-allow-browser-tools]',
    ),
  )
}

function shouldProtectCurrentPage() {
  return !isPublicPath(getCurrentHashPath())
}

function hasAppBridge() {
  return Boolean(window.app || window.webkit || window.FlutterPageControl)
}

function isSuspiciousAutomation() {
  const ua = navigator.userAgent || ''

  return Boolean(
    navigator.webdriver ||
      window.__playwright__binding__ ||
      window.__nightmare ||
      window.callPhantom ||
      /HeadlessChrome|PhantomJS|puppeteer|Playwright/i.test(ua),
  )
}

function isDevtoolsOpen() {
  return (
    window.outerWidth - window.innerWidth > DEVTOOLS_WIDTH_THRESHOLD ||
    window.outerHeight - window.innerHeight > DEVTOOLS_WIDTH_THRESHOLD
  )
}

function redirectToNotApp() {
  if (window.location.hash.startsWith('#/not_app')) {
    return
  }

  window.location.replace(SECURITY_REDIRECT)
}

function guardShortcut(event) {
  if (!shouldProtectCurrentPage() || isEditableElement(event.target)) {
    return
  }

  const key = event.key?.toLowerCase()
  const withCtrlOrMeta = event.ctrlKey || event.metaKey
  const withShift = event.shiftKey

  if (
    event.key === 'F12' ||
    (withCtrlOrMeta && withShift && ['i', 'j', 'c'].includes(key)) ||
    (withCtrlOrMeta && ['u', 's'].includes(key))
  ) {
    event.preventDefault()
    event.stopPropagation()
  }
}

function guardPointerEvent(event) {
  if (!shouldProtectCurrentPage() || isEditableElement(event.target)) {
    return
  }

  event.preventDefault()
  event.stopPropagation()
}

function guardSelectionEvent(event) {
  if (!shouldProtectCurrentPage() || isEditableElement(event.target)) {
    return
  }

  event.preventDefault()
}

function syncSecurityState() {
  const shouldBlur = shouldProtectCurrentPage() && !hasAppBridge() && isDevtoolsOpen()
  document.documentElement.classList.toggle('security-devtools-open', shouldBlur)
}

function injectSecurityStyle() {
  if (document.getElementById('runtime-security-style')) {
    return
  }

  const style = document.createElement('style')
  style.id = 'runtime-security-style'
  style.textContent = `
    html.security-devtools-open body {
      filter: blur(10px);
      pointer-events: none;
      user-select: none;
    }
  `

  document.head.appendChild(style)
}

export function installRuntimeSecurity() {
  if (isDebugMode()) {
    return
  }

  injectSecurityStyle()

  if (shouldProtectCurrentPage() && isSuspiciousAutomation() && !hasAppBridge()) {
    redirectToNotApp()
    return
  }

  document.addEventListener('keydown', guardShortcut, true)
  document.addEventListener('contextmenu', guardPointerEvent, true)
  document.addEventListener('dragstart', guardPointerEvent, true)
  document.addEventListener('copy', guardSelectionEvent, true)
  document.addEventListener('selectstart', guardSelectionEvent, true)
  window.addEventListener('resize', syncSecurityState, { passive: true })
  window.addEventListener('hashchange', syncSecurityState, { passive: true })

  syncSecurityState()
}
