"use client";

import { createContext, useContext, type ReactNode } from "react";
import { ContainmentProvider } from "@enode/ui/containment";
import type { DeviceTarget } from "./devices";

export type ScreenshotTheme = "dark" | "light";

// The tile's theme, provided by MarketingTile and read by every DeviceMock —
// including the hero tile's nested device mocks, which the context reaches
// without prop-drilling through `screen.render`.
export const ScreenshotThemeContext = createContext<ScreenshotTheme>("dark");

// A real device FRAME wrapping the app-screen canvas.
//
// The app screen renders at true logical points (`target.screenW/H`) and is
// scaled to fill the frame's transparent screen cutout, so its native type sizes
// read correctly while the exporter re-rasterizes the DOM crisply at export
// resolution. The frame PNG (bezel + notch/stand) paints ON TOP, with the app
// showing through the transparent cutout.
//
// - iOS look: the screen subtree is wrapped in `class="ios"`, so the app's
//   `ios:` Tailwind variant applies (there is no `.android` variant — Android
//   renders like web).
// - `theme-dark` pins the app's dark token set so exports are deterministic
//   regardless of the viewer's `prefers-color-scheme`.
// - `ContainmentProvider value="container"` confines any overlays/sheets to the
//   screen box instead of the window.
export function DeviceMock({
  target,
  frameWidthPx,
  children,
}: {
  target: DeviceTarget;
  /** On-canvas frame outer width in export px. */
  frameWidthPx: number;
  children: ReactNode;
}) {
  const theme = useContext(ScreenshotThemeContext);
  const { frame } = target;
  // DeviceMock is only rendered for framed targets (the hero tile draws its own
  // device frames onto framed sub-targets); a frameless target has nothing to
  // wrap.
  if (!frame) return null;
  const frameW = frameWidthPx;
  const frameH = frameWidthPx / frame.aspect;
  const cut = frame.cutout;
  const cutW = frameW * cut.w;
  const cutH = frameH * cut.h;
  // Scale the logical app screen to fill the cutout (its aspect is sized to
  // match, so this fills without stretch).
  const screenScale = cutW / target.screenW;
  const isIOS = target.platform === "ios";

  // Top safe-area inset (logical points). The app headers pad down by
  // `env(safe-area-inset-top)`, which resolves to 0 in a browser/mock — so on a
  // phone frame the header content would sit under the Dynamic Island. Reserve
  // the real iOS proportion (~6.5% of the screen height ≈ 62pt on a 6.9" phone)
  // as a top strip so every header clears the island. Both phone frames carry
  // the iPhone Dynamic Island; pads (iPad / Mac) have no notch → 0.
  const safeTopPx =
    target.deviceClass === "phone" ? Math.round(target.screenH * 0.065) : 0;

  return (
    <div
      className="relative shrink-0"
      style={{ width: frameW, height: frameH }}
    >
      {/* App screen, behind the frame, aligned to the transparent cutout. The
          frame's rounded bezel masks the screen's square corners. `theme-dark`/
          `theme-light` pins the app theme so exports are deterministic. */}
      <div
        className={`${theme === "light" ? "theme-light" : "theme-dark"} absolute overflow-hidden bg-background`}
        style={{
          left: frameW * cut.x,
          top: frameH * cut.y,
          width: cutW,
          height: cutH,
        }}
      >
        <div
          className={isIOS ? "ios" : undefined}
          style={{
            width: target.screenW,
            height: target.screenH,
            transform: `scale(${screenScale})`,
            transformOrigin: "top left",
          }}
        >
          <ContainmentProvider value="container">
            {/* box-border so the top safe-area padding eats into the height
                from the top: content (and its frosted headers) starts below the
                Dynamic Island, the strip above shows the app background — just
                like the real status-bar region. Bottom-anchored floating
                elements (nav / load pill) stay pinned to the screen bottom. */}
            <div
              className="relative box-border h-full w-full overflow-hidden bg-background"
              style={{ paddingTop: safeTopPx }}
            >
              {children}
            </div>
          </ContainmentProvider>
        </div>
      </div>

      {/* Frame overlay — the app shows through its transparent screen cutout. */}
      {/* eslint-disable-next-line @next/next/no-img-element */}
      <img
        src={frame.src}
        alt=""
        aria-hidden
        className="pointer-events-none absolute inset-0 z-10"
        style={{ width: frameW, height: frameH }}
      />
    </div>
  );
}
