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 DEFAULT_WIDGET_ASSET_BASE =
  "https://unpkg.com/@eka-care/medassist-widget@latest/dist/";

const scriptEl = getCurrentScript();
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;

  constructor() {
    super();
    this.attachShadow({ mode: "open" });
    this.defaultIconUrl = "./assets/bot-icon.svg";
    this.widgetLoaded = false;
  }

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

  connectedCallback(): void {
    this.renderButton();
  }

  attributeChangedCallback(name: string): void {
    if (name === "icon-url") {
      this.renderButton();
    }
  }

  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;
          }
        </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;
      }
    }
  }

  async loadAndRender(): Promise<void> {
    console.log("MedAssistWidgetLoader loadAndRender");
    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");
    if (!agentId) {
      console.error("Agent ID is required");
      return;
    }

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

    button.classList.add("hidden");
    rootElement.classList.remove("hidden");

    const widgetConfig = {
      title,
      iconUrl,
      environment,
      onClose: () => {
        button.classList.remove("hidden");
        rootElement.classList.add("hidden");
      },
      baseUrl
    };

    if (this.widgetLoaded) {
      window.renderMedAssist?.(rootElement, agentId, 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, agentId, widgetConfig);
      this.widgetLoaded = true;
    } catch (error) {
      console.error("Failed to load MedAssist widget", error);
      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);
