import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react"
import { Box, Checkbox, Group, Select, Text } from "@mantine/core"
import { PRICE } from "@/shared/constants/main"
import { FRAME_TAG, HOOK_SOURCE } from "./constants"
import {
  applyForcedBodyClasses,
  injectHook,
  replacePricePlaceholderInDocument,
} from "./iframe-hook"

type Props = {
  src: string
}

type ViewportPreset = {
  id: string
  label: string
  /** null — на весь доступный блок (десктоп) */
  width: number | null
  height: number | null
}

const VIEWPORT_PRESETS: ViewportPreset[] = [
  { id: "desktop", label: "Десктоп", width: null, height: null },
  { id: "mobile", label: "Мобильный (320×480)", width: 320, height: 480 },
  { id: "iphone-se", label: "iPhone SE (375×667)", width: 375, height: 667 },
  {
    id: "iphone-14",
    label: "iPhone 14 (390×844)",
    width: 390,
    height: 844,
  },
  {
    id: "iphone-14-pro",
    label: "iPhone 14 Pro (393×852)",
    width: 393,
    height: 852,
  },
  {
    id: "iphone-14-pro-max",
    label: "iPhone 14 Pro Max (430×932)",
    width: 430,
    height: 932,
  },
  {
    id: "galaxy-s23",
    label: "Samsung Galaxy S23 (360×780)",
    width: 360,
    height: 780,
  },
  { id: "pixel-7", label: "Google Pixel 7 (412×915)", width: 412, height: 915 },
  {
    id: "ipad-mini",
    label: "iPad mini (768×1024)",
    width: 768,
    height: 1024,
  },
]

const SANDBOX =
  "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"

const PreviewFrame = ({ src }: Props) => {
  const frameRef = useRef<HTMLIFrameElement>(null)
  const devicePreviewContainerRef = useRef<HTMLDivElement>(null)
  const [viewportId, setViewportId] = useState<string>("desktop")
  /** Для пресетов: визуальный scale; сам iframe остаётся в точных логических px устройства. */
  const [deviceFitScale, setDeviceFitScale] = useState(1)

  const [bodyFlags, setBodyFlags] = useState({
    agree: false,
    loader: false,
    close: false,
  })

  const onBodyFlagChange = useCallback(
    (key: "agree" | "loader" | "close", value: boolean) => {
      setBodyFlags(prev => ({ ...prev, [key]: value }))
    },
    []
  )

  const preset =
    VIEWPORT_PRESETS.find(p => p.id === viewportId) ?? VIEWPORT_PRESETS[0]
  const isDesktop = preset.width == null || preset.height == null
  const deviceW = preset.width
  const deviceH = preset.height

  useLayoutEffect(() => {
    if (isDesktop || deviceW == null || deviceH == null) return
    const el = devicePreviewContainerRef.current
    if (!el) return

    const update = (entry: ResizeObserverEntry) => {
      const w = entry.contentRect.width
      const h = entry.contentRect.height
      const s = Math.min(w / deviceW, h / deviceH)
      if (Number.isFinite(s) && s > 0) {
        setDeviceFitScale(s)
      }
    }

    const ro = new ResizeObserver(entries => {
      const first = entries[0]
      if (first) update(first)
    })
    ro.observe(el)
    return () => ro.disconnect()
  }, [isDesktop, deviceW, deviceH])

  const applyBody = useCallback(() => {
    const el = frameRef.current
    if (!el) return
    try {
      applyForcedBodyClasses(el.contentDocument, bodyFlags)
    } catch {
      // cross-origin or no document
    }
  }, [bodyFlags])

  useEffect(() => {
    applyBody()
  }, [applyBody])

  const handleLoad = () => {
    const el = frameRef.current
    if (!el) return
    const doc = el.contentDocument
    applyForcedBodyClasses(doc, bodyFlags)
    replacePricePlaceholderInDocument(doc, PRICE)
    injectHook(doc)
    let href = ""
    try {
      href = el.contentWindow?.location?.href ?? ""
    } catch {
      href = "(недоступен — другой origin?)"
    }
    window.postMessage(
      {
        source: HOOK_SOURCE,
        frame: FRAME_TAG,
        kind: "iframe-load",
        payload: { href },
      },
      "*"
    )
  }

  const desktopShellStyle = {
    flex: 1,
    alignSelf: "stretch" as const,
    minHeight: 0,
  }

  return (
    <Box
      component="main"
      flex={1}
      mih={0}
      pos="relative"
      style={{ display: "flex", flexDirection: "column", minHeight: 0 }}
    >
      <Box
        px="sm"
        py="xs"
        style={{
          flexShrink: 0,
          borderBottom: "1px solid var(--mantine-color-default-border)",
          background: "var(--mantine-color-body)",
        }}
      >
        <Group gap="md" wrap="wrap" align="center" justify="space-between">
          <Group gap="sm" wrap="wrap" align="center">
            <Text size="sm" c="dimmed" fw={500}>
              Режим экрана
            </Text>
            <Select
              size="xs"
              w={{ base: "100%", sm: 280 }}
              data={VIEWPORT_PRESETS.map(p => ({
                value: p.id,
                label: p.label,
              }))}
              value={viewportId}
              onChange={v => setViewportId(v ?? "desktop")}
              comboboxProps={{ withinPortal: true }}
            />
          </Group>
          {onBodyFlagChange && (
            <Group
              gap="sm"
              wrap="wrap"
              align="center"
              title="Классы на body внутри iframe"
            >
              <Text size="xs" c="dimmed" fw={500}>
                body
              </Text>
              <Checkbox
                label="agree"
                size="xs"
                checked={bodyFlags.agree}
                onChange={e =>
                  onBodyFlagChange("agree", e.currentTarget.checked)
                }
              />
              <Checkbox
                label="loader"
                size="xs"
                checked={bodyFlags.loader}
                onChange={e =>
                  onBodyFlagChange("loader", e.currentTarget.checked)
                }
              />
              <Checkbox
                label="close"
                size="xs"
                checked={bodyFlags.close}
                onChange={e =>
                  onBodyFlagChange("close", e.currentTarget.checked)
                }
              />
            </Group>
          )}
        </Group>
      </Box>

      <Box
        ref={devicePreviewContainerRef}
        flex={1}
        mih={0}
        pos="relative"
        bg="dark.9"
        style={{
          overflow: "hidden",
          display: "flex",
          alignItems: isDesktop ? "stretch" : "center",
          justifyContent: isDesktop ? "stretch" : "center",
          padding: isDesktop ? 0 : "var(--mantine-spacing-md)",
        }}
      >
        {isDesktop || deviceW == null || deviceH == null ? (
          <Box pos="relative" style={desktopShellStyle}>
            <iframe
              ref={frameRef}
              title="Лендинг"
              src={src || undefined}
              onLoad={handleLoad}
              sandbox={SANDBOX}
              style={{
                position: "absolute",
                inset: 0,
                width: "100%",
                height: "100%",
                border: 0,
                background: "#fff",
                display: "block",
              }}
            />
          </Box>
        ) : (
          <Box
            pos="relative"
            style={{
              width: deviceW * deviceFitScale,
              height: deviceH * deviceFitScale,
              flexShrink: 0,
            }}
          >
            <Box
              pos="absolute"
              left="50%"
              top="50%"
              style={{
                width: deviceW,
                height: deviceH,
                marginLeft: -deviceW / 2,
                marginTop: -deviceH / 2,
                transform: `scale(${deviceFitScale})`,
                transformOrigin: "center center",
                borderRadius: 12,
                overflow: "hidden",
                boxShadow:
                  "0 0 0 1px var(--mantine-color-dark-4), 0 12px 40px rgba(0,0,0,0.45)",
              }}
            >
              <iframe
                ref={frameRef}
                title="Лендинг"
                src={src || undefined}
                onLoad={handleLoad}
                sandbox={SANDBOX}
                width={deviceW}
                height={deviceH}
                style={{
                  width: deviceW,
                  height: deviceH,
                  border: 0,
                  background: "#fff",
                  display: "block",
                }}
              />
            </Box>
          </Box>
        )}
      </Box>
    </Box>
  )
}

export default PreviewFrame
