const getCurrentScript = (): HTMLScriptElement | null => {
  if (typeof document === "undefined") {
    console.error("document is not defined");
    return null;
  }

  const { currentScript } = document;
  if (currentScript instanceof HTMLScriptElement) {
    return currentScript;
  }

  const scripts = document.getElementsByTagName("script");
  return scripts.length ? scripts[scripts.length - 1] : null;
};

type WidgetEnvironment = "production" | "development" | "staging";

const getEnvironment = (
  value: string | null
): WidgetEnvironment | undefined => {
  if (
    value === "production" ||
    value === "development" ||
    value === "staging"
  ) {
    return value;
  }
  return undefined;
};

const scriptEl = getCurrentScript();

// Detect version tag from script src (e.g., @dev, @latest)
const DEFAULT_WIDGET_ASSET_BASE = (() => {
  if (scriptEl?.src?.includes("@dev")) {
    return "https://unpkg.com/@eka-care/medassist-widget@dev/dist/";
  }
  return "https://unpkg.com/@eka-care/medassist-widget@latest/dist/";
})();

type MedAssistInitConfig = {
  auth?: string;
  agentId?: string;
  context?: Record<string, unknown>;
  title?: string;
  iconUrl?: string;
  baseUrl?: string;
  [key: string]: unknown;
};

interface EkaMedAssistWindow extends Window {
  EkaMedAssist?: {
    init: (config: MedAssistInitConfig) => void;
    onClose?: () => void;
  };
  __ekaMedAssistConfig__?: MedAssistInitConfig;
}

const globalMedAssistConfig: MedAssistInitConfig = {};

const getWidgetElement = (): HTMLElement | null => {
  if (typeof document === "undefined") {
    return null;
  }
  return document.querySelector("eka-medassist-widget");
};

if (typeof window !== "undefined") {
  const w = window as EkaMedAssistWindow;
  w.__ekaMedAssistConfig__ = globalMedAssistConfig;

  w.EkaMedAssist = {
    init(config: MedAssistInitConfig) {
      Object.assign(globalMedAssistConfig, config);
      const el = getWidgetElement();
      if (!el) return;

      if (config.agentId) el.setAttribute("agent-id", config.agentId);
      if (config.title) el.setAttribute("title", config.title);
      if (config.iconUrl) el.setAttribute("icon-url", config.iconUrl);
      if (config.baseUrl) el.setAttribute("base-url", config.baseUrl);
      if (config.context) {
        try {
          el.setAttribute("context", JSON.stringify(config.context));
        } catch {
          console.warn("Failed to stringify context passed to init");
        }
      }

      (el as any).openFromBridge?.();
    },
  };
}

const scriptBaseUrl = (() => {
  if (!scriptEl) {
    return "";
  }
  try {
    return new URL(".", scriptEl.src || window.location.href).href;
  } catch {
    return "";
  }
})();

const widgetAssetBaseUrl = (() => {
  if (!scriptEl) {
    return DEFAULT_WIDGET_ASSET_BASE;
  }

  const dataValue = scriptEl.dataset.widgetAssets;
  if (dataValue === "local") {
    return `${scriptBaseUrl}src/`;
  }

  if (dataValue && dataValue.length > 0) {
    try {
      return new URL(dataValue, scriptBaseUrl).href;
    } catch {
      return dataValue.endsWith("/") ? dataValue : `${dataValue}/`;
    }
  }

  return DEFAULT_WIDGET_ASSET_BASE;
})();

const WIDGET_JS_URL = `${widgetAssetBaseUrl}medassist-widget.js`;
const WIDGET_CSS_URL = `${widgetAssetBaseUrl}medassist-widget.css`;

let widgetScriptPromise: Promise<void> | null = null;
let widgetCssTextPromise: Promise<string> | null = null;

class MedAssistWidgetLoader extends HTMLElement {
  private defaultIconUrl: string;
  private widgetLoaded: boolean;
  private displayMode: "full" | "widget";

  constructor() {
    super();
    this.attachShadow({ mode: "open" });
    this.defaultIconUrl = "https://cdn.eka.care/bot-icon.svg";
    this.widgetLoaded = false;
    this.displayMode = this.getAttribute("display-mode") === "full" ? "full" : "widget";

    this.preloadResources();
    // Listen for AUTH_EXPIRED events from the widget and forward to parent
    this.setupAuthExpirationListener();
  }

  static get observedAttributes(): string[] {
    return ["icon-url", "display-mode"];
  }

  connectedCallback(): void {
    if (this.displayMode === "full") {
      this.initializeFullMode();
    } else {
      this.renderButton();
    }
  }

  attributeChangedCallback(name: string): void {
    if (name === "icon-url") {
      if (this.displayMode === "widget") {
        this.renderButton();
      }
    }
    if (name === "display-mode") {
      const newMode = this.getAttribute("display-mode") === "full" ? "full" : "widget";
      if (newMode !== this.displayMode) {
        this.displayMode = newMode;
        if (newMode === "full") {
          this.initializeFullMode();
        } else {
          this.renderButton();
        }
      }
    }
  }

  // Preload resources in the background
  private preloadResources(): void {
    // Preload CSS (browser will cache it)
    if (!document.querySelector(`link[href="${WIDGET_CSS_URL}"]`)) {
      const cssLink = document.createElement("link");
      cssLink.rel = "preload";
      cssLink.href = WIDGET_CSS_URL;
      cssLink.as = "style";
      document.head.appendChild(cssLink);
    }

    // Preload JS (browser will cache it)
    if (!document.querySelector(`link[href="${WIDGET_JS_URL}"]`)) {
      const jsLink = document.createElement("link");
      jsLink.rel = "preload";
      jsLink.href = WIDGET_JS_URL;
      jsLink.as = "script";
      jsLink.crossOrigin = "anonymous";
      document.head.appendChild(jsLink);
    }
  }

  private setupAuthExpirationListener(): void {
    if (typeof window === "undefined") return;

    const messageHandler = (event: MessageEvent) => {
      if (event.data?.type === "AUTH_EXPIRED") {
        if (window.parent !== window) {
          window.parent.postMessage({ type: "AUTH_EXPIRED", message: "Authentication expired" }, "*");
        }
        // window.webkit.messageHandlers.authTokenExpired.postMessage({});
      }
    }

    window.addEventListener("message", messageHandler);
  }

  public openFromBridge(): void {
    this.displayMode = this.getAttribute("display-mode") === "full" ? "full" : "widget";
    if (this.displayMode === "full") {
      this.initializeFullMode();
    } else {
      this.renderButton();
    }

    Promise.all([this.loadWidgetCss(), this.loadWidgetScript()])
      .then(() => this.loadAndRender())
      .catch((error) => {
        console.error("Failed to open MedAssist widget from bridge", error);
      });
  }

  renderButton(): void {
    const iconUrl = this.getAttribute("icon-url") || this.defaultIconUrl;
    const shadowRoot = this.shadowRoot;

    if (!shadowRoot) {
      console.error("Shadow root was not created");
      return;
    }

    if (!shadowRoot.querySelector("button")) {
      shadowRoot.innerHTML = `
        <style>
          #medassist-open-btn {
            width: 60px;
            height: 60px;
            border-radius: 50%;
            border: none;
            cursor: pointer;
            background-color:rgb(255, 255, 255);
            padding: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
          }
          #medassist-open-btn img {
            width: 30px;
            height: 30px;
          }
          :host {
            position: fixed;
            bottom: 20px;
            right: 20px;
            z-index: 200000;
          }
          #medassist-open-btn:hover {
            background-color:rgb(239, 237, 245);
          }
          .hidden {
            display: none !important;
          }
          #medassist-open-btn.hidden {
            display: none !important;
          }
        </style>

        <button id="medassist-open-btn">
          <img src="${iconUrl}" alt="MedAssist Icon">
        </button>
        <div id="medassist-widget-root" class="hidden"></div>
      `;

      shadowRoot
        .getElementById("medassist-open-btn")
        ?.addEventListener("click", () => this.loadAndRender());
    } else {
      const img = shadowRoot.querySelector<HTMLImageElement>(
        "#medassist-open-btn img"
      );
      if (img) {
        img.src = iconUrl;
      }
    }
  }

  initializeFullMode(): void {
    const shadowRoot = this.shadowRoot;
    if (!shadowRoot) {
      console.error("Shadow root is not available");
      return;
    }

    if (!shadowRoot.getElementById("medassist-widget-root")) {
      shadowRoot.innerHTML = `
        <style>
         :host {
         display: block;
         width: 100%;
         height: 100%;
         position: fixed;
         top: 0;
         left: 0;
         z-index: 200000;
         }
           #medassist-widget-root {
            width: 100%;
            height: 100%;
          }
        </style>
        <div id="medassist-widget-root"></div>
      `;
    }
  }

  async loadAndRender(): Promise<void> {
    const shadowRoot = this.shadowRoot;
    if (!shadowRoot) {
      console.error("Shadow root is not available");
      return;
    }

    const button = shadowRoot.getElementById("medassist-open-btn");
    const rootElement = shadowRoot.getElementById("medassist-widget-root");
    const agentId = this.getAttribute("agent-id");
    const iconUrl = this.getAttribute("icon-url") || this.defaultIconUrl;
    const environment =
      getEnvironment(this.getAttribute("environment")) ?? "production";
    const title = this.getAttribute("title") || "Medi Clinic";
    const baseUrl = this.getAttribute("base-url") || undefined;
    const displayModeAttribute = this.getAttribute("display-mode");
    const displayMode: "full" | "widget" = displayModeAttribute === "full" ? "full" : "widget";
    const attributeContext = this.getAttribute("context") ? JSON.parse(this.getAttribute("context") || "{}") : undefined;

    const initConfig = (typeof window !== "undefined"
      ? (window as EkaMedAssistWindow).__ekaMedAssistConfig__
      : undefined) || {};

    const mergedContext = {
      ...(attributeContext || {}),
      ...(initConfig.context || {}),
    };

    const auth = initConfig.auth || undefined;
    const resolvedAgentId = initConfig.agentId || agentId;

    const customOnClose = typeof window !== "undefined" ? (window as EkaMedAssistWindow).EkaMedAssist?.onClose : undefined;

    if (!resolvedAgentId) {
      console.error("Agent ID is required");
      return;
    }

    if (!rootElement) {
      console.error("Widget root element is missing");
      return;
    }

    if (button) {
      button.classList.add("hidden");
    }
    rootElement.classList.remove("hidden");

    const widgetConfig = {
      title: (initConfig.title as string) || title,
      iconUrl: (initConfig.iconUrl as string) || iconUrl,
      environment,
      onClose: () => {
        if (customOnClose && typeof customOnClose === "function") {
          customOnClose();
        }
        if (button) {
          button.classList.remove("hidden");
        }
        rootElement.classList.add("hidden");

      },
      baseUrl: (initConfig.baseUrl as string) || baseUrl,
      context: mergedContext,
      displayMode,
      auth
    };

    if (this.widgetLoaded) {
      window.renderMedAssist?.(rootElement, resolvedAgentId, widgetConfig);
      return;
    }

    try {
      await Promise.all([this.loadWidgetCss(), this.loadWidgetScript()]);
      if (typeof window.renderMedAssist !== "function") {
        throw new Error("renderMedAssist is not available on window");
      }

      window.renderMedAssist(rootElement, resolvedAgentId, widgetConfig);
      this.widgetLoaded = true;
    } catch (error) {
      console.error("Failed to load MedAssist widget", error);
      if (button) {
        button.classList.remove("hidden");
      }
      rootElement.classList.add("hidden");
    }
  }

  async loadWidgetCss(): Promise<void> {
    const shadowRoot = this.shadowRoot;
    if (!shadowRoot) {
      throw new Error("Shadow root is not available");
    }

    if (shadowRoot.querySelector("[data-medassist-style='true']")) {
      return;
    }

    if (!widgetCssTextPromise) {
      widgetCssTextPromise = fetch(WIDGET_CSS_URL).then((response) => {
        if (!response.ok) {
          throw new Error(
            `Unable to fetch widget styles from ${WIDGET_CSS_URL}`
          );
        }
        return response.text();
      });
    }

    const cssText = await widgetCssTextPromise;
    const styleTag = document.createElement("style");
    styleTag.setAttribute("data-medassist-style", "true");
    styleTag.textContent = cssText;
    shadowRoot.appendChild(styleTag);
  }

  loadWidgetScript(): Promise<void> {
    if (!widgetScriptPromise) {
      widgetScriptPromise = new Promise<void>((resolve, reject) => {
        const existingScript = document.querySelector<HTMLScriptElement>(
          `script[src="${WIDGET_JS_URL}"]`
        );

        if (existingScript) {
          if (existingScript.dataset.loaded === "true") {
            resolve();
            return;
          }
          existingScript.addEventListener("load", () => resolve());
          existingScript.addEventListener("error", (event) =>
            reject(event.error || new Error("Unknown script loading error"))
          );
          return;
        }

        const script = document.createElement("script");
        script.src = WIDGET_JS_URL;
        script.async = true;
        script.dataset.widget = "medassist";

        script.onload = () => {
          script.dataset.loaded = "true";
          resolve();
        };
        script.onerror = (event) => {
          if (event instanceof ErrorEvent && event.error) {
            reject(event.error);
            return;
          }
          reject(new Error(`Failed to load ${WIDGET_JS_URL}`));
        };

        document.head.appendChild(script);
      });
    }

    return widgetScriptPromise;
  }
}

customElements.define("eka-medassist-widget", MedAssistWidgetLoader);
