import { core } from "../core.js";
import { toastHelper } from "../viewer-utils.js";
import { t } from "../i18n-utils.js";

export function attachEmbedConfigurator(Viewer) {
  Object.assign(Viewer, {
    isEmbedModeActive() {
      return this.embedConfiguratorPanel?.hidden === false;
    },

    isEmbedMode() {
      const params = new URLSearchParams(window.location.search);
      const embedParam = params.get("embed");
      return window.location.pathname.endsWith("/embed.html") || embedParam === "1" || embedParam === "true";
    },

    getEmbedPageUrl() {
      const embedUrl = new URL("embed.html", import.meta.url);
      embedUrl.search = "";
      embedUrl.hash = "";
      return embedUrl;
    },

    async copyTextToClipboard(value) {
      if (navigator.clipboard?.writeText) {
        await navigator.clipboard.writeText(value);
        return;
      }

      const tempInput = document.createElement("textarea");
      tempInput.value = value;
      tempInput.setAttribute("readonly", "true");
      tempInput.style.position = "absolute";
      tempInput.style.left = "-9999px";
      document.body.appendChild(tempInput);
      tempInput.select();
      document.execCommand("copy");
      tempInput.remove();
    },

    getCurrentEmbedOptions({ includeCamera = false } = {}) {
      const entityId = core.CONFIG?.entity?.id;
      const modelPath = core.fileObject?.originalPath || core.container?.getAttribute("3d") || "";
      const options = {
        model: modelPath || null,
        id: entityId || null,
        theme: this.currentTheme === "light" ? "light" : null,
        autorotate: core.controls?.autoRotate === true,
        autorotateSpeed: Number.isFinite(core.controls?.autoRotateSpeed) ? core.controls.autoRotateSpeed : null,
        disableInteraction: this.urlOptions?.disableInteraction === true,
        hideUi: this.urlOptions?.hideUi === true,
        hideMetadata: this.urlOptions?.hideMetadata === true,
        presentationMode: core.PRESENTATION_MODE === true,
        sandboxMode: core.SANDBOX_MODE === true,
        cameraPosition: null,
        cameraTarget: null,
        fov: null,
      };

      if (includeCamera) {
        options.cameraPosition = this.formatVector3Param(core.camera?.position);
        options.cameraTarget = this.formatVector3Param(core.controls?.target);
        options.fov = Number.isFinite(core.camera?.fov) ? core.camera.fov : null;
      }

      return options;
    },

    applyEmbedOptionsToInputs(options = {}) {
      console.log(this.embedConfigInputs);
      if (!this.embedConfigInputs) return;
      this.embedConfigInputs.model.value = options.model ?? "";
      this.embedConfigInputs.id.value = options.id ?? "";
      this.embedConfigInputs.theme.value = options.theme === "light" ? "light" : "dark";
      this.embedConfigInputs.autorotate.checked = options.autorotate === true;
      this.embedConfigInputs.autorotateSpeed.value = Number.isFinite(options.autorotateSpeed) ? String(options.autorotateSpeed) : "";
      this.embedConfigInputs.disableInteraction.checked = options.disableInteraction === true;
      this.embedConfigInputs.hideUi.checked = options.hideUi === true;
      this.embedConfigInputs.hideMetadata.checked = options.hideMetadata === true;
      this.embedConfigInputs.presentationMode.checked = options.presentationMode === true;
      this.embedConfigInputs.camPos.value = options.cameraPosition ?? "";
      this.embedConfigInputs.camTarget.value = options.cameraTarget ?? "";
      this.embedConfigInputs.fov.value = Number.isFinite(options.fov) ? String(options.fov) : "";
      console.log(
  "fillConfiguratorWithCurrentCamera",
  this.embedConfigInputs.camPos.value
);
    },

    setEmbedInputError(input, hasError, message = "") {
      if (!input) return;
      input.classList.toggle("embed-input-invalid", hasError);
      if (hasError && message) {
        input.setAttribute("title", message);
        input.setAttribute("aria-invalid", "true");
      } else {
        input.removeAttribute("title");
        input.removeAttribute("aria-invalid");
      }
    },

    validateEmbedInputFields() {
      if (!this.embedConfigInputs) return true;
      const { camPos, camTarget, fov } = this.embedConfigInputs;
      const camPosRaw = camPos.value.trim();
      const camTargetRaw = camTarget.value.trim();
      const fovRaw = fov.value.trim();

      const camPosOk = camPosRaw === "" || this.parseVector3Param(camPosRaw) !== null;
      const camTargetOk = camTargetRaw === "" || this.parseVector3Param(camTargetRaw) !== null;
      const parsedFov = this.parseFloatParam(fovRaw);
      const fovOk = fovRaw === "" || (Number.isFinite(parsedFov) && parsedFov >= 1 && parsedFov <= 179);

      this.setEmbedInputError(camPos, !camPosOk, "Use format: x,y,z (for example 1.2,0.8,2.5)");
      this.setEmbedInputError(camTarget, !camTargetOk, "Use format: x,y,z (for example 0,0,0)");
      this.setEmbedInputError(fov, !fovOk, "FOV must be a number from 1 to 179");

      return camPosOk && camTargetOk && fovOk;
    },

    buildEmbedPayload(options = {}) {
      const embedUrl = this.getEmbedPageUrl();
      const params = new URLSearchParams();

      if (options.model) {
        params.set("model", options.model);
      } else if (options.id) {
        params.set("id", options.id);
      }

      if (options.theme === "light") {
        params.set("theme", options.theme);
      }

      if (options.autorotate === true) {
        params.set("autorotate", "1");
        if (Number.isFinite(options.autorotateSpeed)) {
          params.set("autorotateSpeed", String(options.autorotateSpeed));
        }
      }

      if (options.disableInteraction) {
        params.set("disableInteraction", "1");
      }
      if (options.hideUi) {
        params.set("hideUi", "1");
      }
      if (options.hideMetadata) {
        params.set("hideMetadata", "1");
      }
      if (options.presentationMode) {
        params.set("presentationMode", "1");
      }
      if (options.sandboxMode) {
        params.set("sandbox", "1");
      }
      if (options.cameraPosition) {
        params.set("camPos", options.cameraPosition);
      }
      if (options.cameraTarget) {
        params.set("camTarget", options.cameraTarget);
      }
      if (Number.isFinite(options.fov)) {
        params.set("fov", String(options.fov));
      }

      embedUrl.search = params.toString();

      return {
        url: embedUrl.toString(),
        code: `<iframe src="${embedUrl.toString()}" title="DFG 3D Viewer" loading="lazy" allow="fullscreen; xr-spatial-tracking" referrerpolicy="strict-origin-when-cross-origin" style="width:100%; aspect-ratio: 16 / 9; border: 0;"></iframe>`,
      };
    },

    getSharePayload() {
      return this.buildEmbedPayload(this.getCurrentEmbedOptions({ includeCamera: true }));
    },

    collectEmbedConfiguratorOptions() {
      console.trace("collectEmbedConfiguratorOptions");
      const inputs = this.embedConfigInputs;
      if (!inputs) return this.getCurrentEmbedOptions({ includeCamera: true });
      const parsedCamPos = this.parseVector3Param(inputs.camPos.value);
      const parsedCamTarget = this.parseVector3Param(inputs.camTarget.value);
      const parsedFov = this.parseFloatParam(inputs.fov.value);
      const normalizedFov = Number.isFinite(parsedFov) ? Math.min(179, Math.max(1, parsedFov)) : null;
      return {
        model: inputs.model.value.trim() || null,
        id: inputs.id.value.trim() || null,
        theme: inputs.theme.value === "light" ? "light" : null,
        autorotate: inputs.autorotate.checked,
        autorotateSpeed: this.parseFloatParam(inputs.autorotateSpeed.value),
        disableInteraction: inputs.disableInteraction.checked,
        hideUi: inputs.hideUi.checked,
        hideMetadata: inputs.hideMetadata.checked,
        presentationMode: inputs.presentationMode.checked,
        cameraPosition: this.formatVector3Param(parsedCamPos),
        cameraTarget: this.formatVector3Param(parsedCamTarget),
        fov: normalizedFov,
      };
    },

    hasEmbedSourceSelection(options = {}) {
      return Boolean(options.model || options.id);
    },

    notifyMissingEmbedSource({ force = false } = {}) {
      if (!force && this.embedMissingSourceNotified) return;
      toastHelper("embedSourceMissing", "warning");
      this.embedMissingSourceNotified = true;
    },

    updateEmbedConfiguratorPreview() {
      if (!this.embedConfigInputs) return;
      if (this.updatingEmbedFields) return;
      this.validateEmbedInputFields();
      const options = this.collectEmbedConfiguratorOptions();
      if (!this.hasEmbedSourceSelection(options)) {
        this.notifyMissingEmbedSource();
      } else {
        this.embedMissingSourceNotified = false;
      }
      const payload = this.buildEmbedPayload(options);
      this.embedConfigInputs.url.value = payload.url;
      this.embedConfigInputs.iframe.value = payload.code;
      if (this.embedConfigPreviewFrame) {
        this.embedConfigPreviewFrame.src = payload.url;
      }
    },

    fillConfiguratorWithCurrentCamera() {
      if (!this.embedConfigInputs) return;

      this.updatingEmbedFields = true;

      this.embedConfigInputs.camPos.value = this.formatVector3Param(core.camera?.position) || "";
      this.embedConfigInputs.camTarget.value = this.formatVector3Param(core.controls?.target) || "";
      this.embedConfigInputs.fov.value = Number.isFinite(core.camera?.fov) ? String(core.camera.fov) : "";
      this.updatingEmbedFields = false;
      this.updateEmbedConfiguratorPreview();
    },

    resetEmbedConfiguratorFromViewerState() {
      if (!this.embedConfigInputs) return;
      this.applyEmbedOptionsToInputs(this.getCurrentEmbedOptions({ includeCamera: true }));
      this.updateEmbedConfiguratorPreview();
    },

    toggleEmbedConfigurator(event) {
      event?.preventDefault?.();
      this.closeActionMenu();
      if (!this.embedConfiguratorPanel) return;
      const willShow = this.embedConfiguratorPanel.hidden === true;
      this.embedConfiguratorPanel.hidden = !willShow;
      if (willShow) {
        this.updateEmbedConfiguratorPreview();
      }
      this.updateEmbedMenuEntryState();
    },

    openEmbedConfiguratorFromMenu(event) {
      this.toggleEmbedConfigurator(event);
    },

    createEmbedConfiguratorPanel() {
      if (!core.container || this.embedConfiguratorPanel) return;
      const defaults = this.getCurrentEmbedOptions({ includeCamera: true });
      const panelText = {
        title: t("embedPanel.title", "Embed options"),
        closeAria: t("embedPanel.closeAria", "Close embed options"),
        modelUrl: t("embedPanel.modelUrl", "Model URL"),
        modelUrlPlaceholder: t("embedPanel.modelUrlPlaceholder", "/examples/box.glb"),
        entityId: t("embedPanel.entityId", "Entity ID"),
        theme: t("embedPanel.theme", "Theme"),
        themeDark: t("embedPanel.themeDark", "Dark"),
        themeLight: t("embedPanel.themeLight", "Light"),
        autoRotateSpeed: t("embedPanel.autoRotateSpeed", "Auto-rotate speed"),
        cameraPosition: t("embedPanel.cameraPosition", "Camera position"),
        cameraTarget: t("embedPanel.cameraTarget", "Camera target"),
        cameraVectorPlaceholder: t("embedPanel.cameraVectorPlaceholder", "x,y,z"),
        fov: t("embedPanel.fov", "FOV"),
        autoRotate: t("embedPanel.autoRotate", "Auto-rotate"),
        disableInteraction: t("embedPanel.disableInteraction", "Disable interaction"),
        hideActionMenu: t("embedPanel.hideActionMenu", "Hide action menu"),
        hideMetadata: t("embedPanel.hideMetadata", "Hide metadata"),
        presentationMode: t("embedPanel.presentationMode", "Presentation mode"),
        useCurrentCamera: t("embedPanel.useCurrentCamera", "Use Current Camera"),
        resetFromViewer: t("embedPanel.resetFromViewer", "Reset From Viewer"),
        copyUrl: t("embedPanel.copyUrl", "Copy URL"),
        copyIframe: t("embedPanel.copyIframe", "Copy Iframe"),
        embedUrl: t("embedPanel.embedUrl", "Embed URL"),
        iframeCode: t("embedPanel.iframeCode", "Iframe code"),
        preview: t("embedPanel.preview", "Preview"),
        previewTitle: t("embedPanel.previewTitle", "Embed preview"),
      };
      const panel = document.createElement("div");
      panel.id = "embedConfiguratorPanel";
      panel.hidden = true;
      panel.innerHTML = `
      <div class="embed-config-header">
        <span>${panelText.title}</span>
        <button id="embedClosePanel" type="button" aria-label="${panelText.closeAria}">X</button>
      </div>
      <div class="embed-config-layout">
        <div class="embed-config-main">
          <div class="embed-config-grid">
            <label>${panelText.modelUrl}<input id="embedModelInput" type="text" placeholder="${panelText.modelUrlPlaceholder}" value="${defaults.model ?? ""}" /></label>
            <label>${panelText.entityId}<input id="embedIdInput" type="text" value="${defaults.id ?? ""}" /></label>
            <label>${panelText.theme}
              <select id="embedThemeInput">
                <option value="dark">${panelText.themeDark}</option>
                <option value="light"${defaults.theme === "light" ? " selected" : ""}>${panelText.themeLight}</option>
              </select>
            </label>
            <label>${panelText.autoRotateSpeed}<input id="embedAutorotateSpeedInput" type="number" step="0.1" value="${Number.isFinite(defaults.autorotateSpeed) ? defaults.autorotateSpeed : ""}" /></label>
            <label>${panelText.cameraPosition}<input id="embedCamPosInput" type="text" placeholder="${panelText.cameraVectorPlaceholder}" value="${defaults.cameraPosition ?? ""}" /></label>
            <label>${panelText.cameraTarget}<input id="embedCamTargetInput" type="text" placeholder="${panelText.cameraVectorPlaceholder}" value="${defaults.cameraTarget ?? ""}" /></label>
            <label>${panelText.fov}<input id="embedFovInput" type="number" step="1" min="1" max="179" value="${Number.isFinite(defaults.fov) ? defaults.fov : ""}" /></label>
          </div>
          <div class="embed-config-checks">
            <label><input id="embedAutorotateInput" type="checkbox"${defaults.autorotate ? " checked" : ""} /> ${panelText.autoRotate}</label>
            <label><input id="embedDisableInteractionInput" type="checkbox"${defaults.disableInteraction ? " checked" : ""} /> ${panelText.disableInteraction}</label>
            <label><input id="embedHideUiInput" type="checkbox"${defaults.hideUi ? " checked" : ""} /> ${panelText.hideActionMenu}</label>
            <label><input id="embedHideMetadataInput" type="checkbox"${defaults.hideMetadata ? " checked" : ""} /> ${panelText.hideMetadata}</label>
            <label><input id="embedPresentationModeInput" type="checkbox"${defaults.presentationMode ? " checked" : ""} /> ${panelText.presentationMode}</label>
          </div>
          <div class="embed-config-actions">
            <button id="embedUseCurrentCamera" type="button">${panelText.useCurrentCamera}</button>
            <button id="embedResetFromViewer" type="button">${panelText.resetFromViewer}</button>
            <button id="embedCopyUrl" type="button">${panelText.copyUrl}</button>
            <button id="embedCopyIframe" type="button">${panelText.copyIframe}</button>
          </div>
          <label class="embed-config-field">${panelText.embedUrl}<textarea id="embedUrlOutput" readonly></textarea></label>
          <label class="embed-config-field">${panelText.iframeCode}<textarea id="embedIframeOutput" readonly></textarea></label>
        </div>
        <div class="embed-config-preview-side">
          <span>${panelText.preview}</span>
          <iframe id="embedPreviewFrame" title="${panelText.previewTitle}" loading="lazy"></iframe>
        </div>
      </div>
    `;

      core.container.appendChild(panel);
      this.embedConfiguratorPanel = panel;
      this.embedConfigInputs = {
        model: panel.querySelector("#embedModelInput"),
        id: panel.querySelector("#embedIdInput"),
        theme: panel.querySelector("#embedThemeInput"),
        autorotate: panel.querySelector("#embedAutorotateInput"),
        autorotateSpeed: panel.querySelector("#embedAutorotateSpeedInput"),
        disableInteraction: panel.querySelector("#embedDisableInteractionInput"),
        hideUi: panel.querySelector("#embedHideUiInput"),
        hideMetadata: panel.querySelector("#embedHideMetadataInput"),
        presentationMode: panel.querySelector("#embedPresentationModeInput"),
        camPos: panel.querySelector("#embedCamPosInput"),
        camTarget: panel.querySelector("#embedCamTargetInput"),
        fov: panel.querySelector("#embedFovInput"),
        url: panel.querySelector("#embedUrlOutput"),
        iframe: panel.querySelector("#embedIframeOutput"),
      };
      this.embedConfigPreviewFrame = panel.querySelector("#embedPreviewFrame");

      const watchedInputs = [
        this.embedConfigInputs.model,
        this.embedConfigInputs.id,
        this.embedConfigInputs.theme,
        this.embedConfigInputs.autorotate,
        this.embedConfigInputs.autorotateSpeed,
        this.embedConfigInputs.disableInteraction,
        this.embedConfigInputs.hideUi,
        this.embedConfigInputs.hideMetadata,
        this.embedConfigInputs.presentationMode,
        this.embedConfigInputs.camPos,
        this.embedConfigInputs.camTarget,
        this.embedConfigInputs.fov,
      ];
      watchedInputs.forEach((input) => {
        if (!input) return;
        const eventName = input.type === "checkbox" || input.tagName === "SELECT" ? "change" : "input";
        this.bindEventListener(input, eventName, () => this.updateEmbedConfiguratorPreview());
      });

      const useCurrentCameraButton = panel.querySelector("#embedUseCurrentCamera");
      const resetFromViewerButton = panel.querySelector("#embedResetFromViewer");
      const copyUrlButton = panel.querySelector("#embedCopyUrl");
      const copyIframeButton = panel.querySelector("#embedCopyIframe");
      const closePanelButton = panel.querySelector("#embedClosePanel");

      this.bindEventListener(useCurrentCameraButton, "click", () => this.fillConfiguratorWithCurrentCamera());
      this.bindEventListener(resetFromViewerButton, "click", () => this.resetEmbedConfiguratorFromViewerState());
      this.bindEventListener(closePanelButton, "click", () => {
        this.closeEmbedConfigurator();
      });
      this.bindEventListener(copyUrlButton, "click", async () => {
        try {
          const options = this.collectEmbedConfiguratorOptions();
          if (!this.hasEmbedSourceSelection(options)) {
            this.notifyMissingEmbedSource({ force: true });
            return;
          }
          const payload = this.buildEmbedPayload(options);
          await this.copyTextToClipboard(payload.url);
          toastHelper("embedUrlCopied", "success");
        } catch (error) {
          this.reportError(error, { context: "Copy embed URL failed" });
          toastHelper("embedUrlCopyError", "error");
        }
      });
      this.bindEventListener(copyIframeButton, "click", async () => {
        try {
          const options = this.collectEmbedConfiguratorOptions();
          if (!this.hasEmbedSourceSelection(options)) {
            this.notifyMissingEmbedSource({ force: true });
            return;
          }
          const payload = this.buildEmbedPayload(options);
          await this.copyTextToClipboard(payload.code);
          toastHelper("embedIframeCopied", "success");
        } catch (error) {
          this.reportError(error, { context: "Copy embed iframe failed" });
          toastHelper("embedIframeCopyError", "error");
        }
      });

      this.updateEmbedConfiguratorPreview();
    },

    async copyEmbedCode(event) {
      event?.preventDefault?.();
      this.closeActionMenu();

      try {
        const { code } = this.getSharePayload();
        await this.copyTextToClipboard(code);
        toastHelper("embedCodeCopied", "success");
      } catch (error) {
        this.reportError(error, { context: "Copy embed code failed" });
        toastHelper("embedCodeCopyError", "error");
      }
    },

    updateEmbedMenuEntryState() {
      if (!this.viewEntity) return;
      const isActive = this.isEmbedModeActive();
      const label = isActive ? t("menu.exitEmbed", "Exit embed") : t("menu.embed", "Embed");
      const iconClass = isActive ? "embed-exit-icon" : "embed-icon";
      this.viewEntity.innerHTML = `<span class="${iconClass}"></span><span>${label}</span>`;
      const a11yLabel = isActive
        ? t("menu.exitEmbedMode", "Exit embed mode")
        : t("menu.openEmbedOptions", "Open embed options");
      this.viewEntity.setAttribute("aria-label", a11yLabel);
      this.viewEntity.setAttribute("title", a11yLabel);
    },

    closeEmbedConfigurator() {
      if (this.embedConfiguratorPanel) {
        this.embedConfiguratorPanel.hidden = true;
      }
      this.updateEmbedMenuEntryState();
    },

    closeEmbedMode() {
      this.closeEmbedConfigurator();
    },
  });
}
