import "./assets/main.css"
import "./i18n"

import { StrictMode } from "react"
import { createRoot } from "react-dom/client"
import App from "./App"
import { ClientContext } from "./ClientContext"
import { StudentService } from "./services/StudentService"
import { ServiceProvider } from "./contexts/ServiceContext"
import { api } from "./preload/types"

if (!(window as any).api) {
  ;(window as any).api = api
}

const ctx = new ClientContext()
new StudentService(ctx)

const safeWriteLog = (payload: {
  level: "debug" | "info" | "warn" | "error"
  message: string
  meta?: any
}) => {
  try {
    const api = (window as any).api
    if (!api?.writeLog) return
    Promise.resolve(api.writeLog(payload)).catch(() => void 0)
  } catch {
    return
  }
}

const patchConsole = () => {
  const c = window.console as any
  const original = {
    log: typeof c.log === "function" ? c.log.bind(c) : undefined,
    info: typeof c.info === "function" ? c.info.bind(c) : undefined,
    warn: typeof c.warn === "function" ? c.warn.bind(c) : undefined,
    debug: typeof c.debug === "function" ? c.debug.bind(c) : undefined,
    error: typeof c.error === "function" ? c.error.bind(c) : undefined,
    trace: typeof c.trace === "function" ? c.trace.bind(c) : undefined,
    table: typeof c.table === "function" ? c.table.bind(c) : undefined,
  }
  const set = (name: string, fn: (...args: any[]) => void) => {
    try {
      c[name] = fn
    } catch {
      void 0
    }
  }

  set("log", (...args: any[]) => {
    safeWriteLog({ level: "info", message: String(args[0] ?? ""), meta: args.slice(1) })
    original.log?.(...args)
  })
  set("info", (...args: any[]) => {
    safeWriteLog({ level: "info", message: String(args[0] ?? ""), meta: args.slice(1) })
    original.info?.(...args)
  })
  set("warn", (...args: any[]) => {
    safeWriteLog({ level: "warn", message: String(args[0] ?? ""), meta: args.slice(1) })
    original.warn?.(...args)
  })
  set("debug", (...args: any[]) => {
    safeWriteLog({ level: "debug", message: String(args[0] ?? ""), meta: args.slice(1) })
    original.debug?.(...args)
  })
  set("error", (...args: any[]) => {
    const first = args[0]
    if (first instanceof Error) {
      safeWriteLog({
        level: "error",
        message: first.message,
        meta: { stack: first.stack, args: args.slice(1) },
      })
      original.error?.(...args)
      return
    }
    safeWriteLog({ level: "error", message: String(first ?? ""), meta: args.slice(1) })
    original.error?.(...args)
  })
  set("trace", (...args: any[]) => {
    safeWriteLog({
      level: "debug",
      message: "console.trace",
      meta: { args, stack: new Error("console.trace").stack },
    })
    original.trace?.(...args)
  })
  set("table", (...args: any[]) => {
    safeWriteLog({ level: "info", message: "console.table", meta: args })
    original.table?.(...args)
  })
}
patchConsole()

const disableTouchZoom = () => {
  let lastTouchEnd = 0

  // iOS Safari/WebView 手势事件，直接阻止页面缩放
  for (const type of ["gesturestart", "gesturechange", "gestureend"]) {
    document.addEventListener(
      type,
      (event) => {
        event.preventDefault()
      },
      { passive: false }
    )
  }

  // 双指触摸移动时阻止缩放
  document.addEventListener(
    "touchmove",
    (event) => {
      if (event.touches.length > 1) {
        event.preventDefault()
      }
    },
    { passive: false }
  )

  // 连续快速双击时阻止浏览器放大
  document.addEventListener(
    "touchend",
    (event) => {
      const now = Date.now()
      if (now - lastTouchEnd <= 300) {
        event.preventDefault()
      }
      lastTouchEnd = now
    },
    { passive: false }
  )

  // 部分环境下双击会触发 dblclick，补充阻止
  document.addEventListener(
    "dblclick",
    (event) => {
      event.preventDefault()
    },
    { passive: false }
  )
}
disableTouchZoom()

// 桌面端触屏窗口拖动支持
const enableTouchWindowDrag = () => {
  const api = (window as any).api
  if (!api) return

  let touchStartX = 0
  let touchStartY = 0
  let isDragging = false
  let dragElement: Element | null = null

  document.addEventListener(
    "touchstart",
    (event) => {
      const target = event.target as Element
      if (!target) return

      // 检查是否在可拖动区域内
      const dragRegion = target.closest("[data-tauri-drag-region]")
      if (!dragRegion) return

      // 检查是否点击了不可拖动的元素（如按钮）
      const noDragElement = target.closest('button, input, select, a, [role="button"]')
      if (noDragElement) return

      const touch = event.touches[0]
      if (!touch) return

      touchStartX = touch.clientX
      touchStartY = touch.clientY
      isDragging = true
      dragElement = dragRegion
    },
    { passive: true }
  )

  document.addEventListener(
    "touchmove",
    (event) => {
      if (!isDragging || !dragElement) return

      const touch = event.touches[0]
      if (!touch) return

      const deltaX = touch.clientX - touchStartX
      const deltaY = touch.clientY - touchStartY

      // 只有当移动距离超过阈值时才认为是拖动窗口
      if (Math.abs(deltaX) > 3 || Math.abs(deltaY) > 3) {
        event.preventDefault()
        api.startDraggingWindow?.()
        isDragging = false
        dragElement = null
      }
    },
    { passive: false }
  )

  document.addEventListener(
    "touchend",
    () => {
      isDragging = false
      dragElement = null
    },
    { passive: true }
  )

  document.addEventListener(
    "touchcancel",
    () => {
      isDragging = false
      dragElement = null
    },
    { passive: true }
  )
}
enableTouchWindowDrag()

const platform = navigator.userAgent.toLowerCase()
const isIos = /iphone|ipad|ipod/.test(platform)
const isAndroid = platform.includes("android")
const isMacDesktop = platform.includes("mac") && !isIos

if (isMacDesktop) {
  document.documentElement.classList.add("platform-macos")
}

if (isIos) {
  document.documentElement.classList.add("platform-ios")
}

if (isAndroid) {
  document.documentElement.classList.add("platform-android")
}

window.addEventListener("error", (e: any) => {
  const error = e?.error
  safeWriteLog({
    level: "error",
    message: "renderer:error",
    meta: {
      message: error?.message || e?.message,
      stack: error?.stack,
      filename: e?.filename,
      lineno: e?.lineno,
      colno: e?.colno,
    },
  })
})

window.addEventListener("unhandledrejection", (e: any) => {
  const reason = e?.reason
  safeWriteLog({
    level: "error",
    message: "renderer:unhandledrejection",
    meta: reason instanceof Error ? { message: reason.message, stack: reason.stack } : { reason },
  })
})

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <ServiceProvider value={ctx}>
      <App />
    </ServiceProvider>
  </StrictMode>
)
