import { IRegion, region } from "@uxland/regions";
import { LitElement, css, html, unsafeCSS } from "lit";
import { state } from "lit/decorators.js";
import { PrimariaRegionHost, shellApi } from "../../../api/api";
import { disposeShell } from "../../../disposer";
import { BROKER_EVENTS } from "../../../api/broker/broker-events";
import { translate } from "../../../locales";
import { shellViews } from "./constants";
import styles from "./styles.css?inline";
import { template } from "./template";
import { BrokerDisposableHandler } from "@uxland/harmonix";

export class PrimariaShell extends PrimariaRegionHost(LitElement) {
  render() {
    return html`${template(this)}`;
  }

  static styles = css`
    ${unsafeCSS(styles)}
  `;

  connectedCallback() {
    super.connectedCallback();
    this._subscribeEvents();
  }

  disconnectedCallback() {
    super.disconnectedCallback();
    this._unsubscribeEvents();
  }

  @region({ targetId: "menu-region-container", name: shellApi.regionManager.regions.shell.navigationMenu })
  navigationMenuRegion: IRegion | undefined;

  @region({ targetId: "main-region-container", name: shellApi.regionManager.regions.shell.main })
  mainRegion: IRegion | undefined;

  @region({ targetId: "quick-actions-region-container", name: shellApi.regionManager.regions.shell.quickActions })
  quickActionsRegion: IRegion | undefined;

  @region({ targetId: "floating-region-container", name: shellApi.regionManager.regions.shell.floating })
  floatingRegion: IRegion | undefined;

  @region({
    targetId: "navigation-menu-lower-region-container",
    name: shellApi.regionManager.regions.shell.navigationLowerLeftMenu,
  })
  navLowerLeftMenu: IRegion | undefined;

  @state()
  sidebarExpanded = false;

  @state()
  viewSelected = shellViews.shell;

  @state()
  error: { message: string };

  @state()
  quickActionBusy = false;

  _toggleSidebar() {
    this.sidebarExpanded = !this.sidebarExpanded;
  }

  private subscriptions: BrokerDisposableHandler[] = [];

  _subscribeEvents() {
    this.subscriptions.push(
      shellApi.broker.subscribe(BROKER_EVENTS.shell.appCrashed, (error: { message: string }) => {
        this._handleError(error);
      }),
    );

    this.subscriptions.push(
      shellApi.broker.subscribe(BROKER_EVENTS.shell.refreshTokenFailed, (detail: any) => {
        this._handleError({ message: translate("errors.session") });
      }),
    );

    this.subscriptions.push(
      shellApi.broker.subscribe(BROKER_EVENTS.shell.mpidHeaderInvalid, (detail: any) => {
        this._handleError({ message: translate("errors.invalidPatient") });
      }),
    );

    this.subscriptions.push(
      shellApi.broker.subscribe(BROKER_EVENTS.shell.quickActionBusyChanged, (detail: { busy: boolean }) => {
        this.quickActionBusy = detail.busy;
      }),
    );

    this.subscriptions.push(
      shellApi.broker.subscribe(BROKER_EVENTS.shell.scrollToNavItemRequested, (navItemMenuKey: string) => {
        this._scrollToNavItem(navItemMenuKey);
      }),
    );
  }

  _handleError(error: { message: string }) {
    this.viewSelected = shellViews.error;
    this.error = error;
    disposeShell();
  }

  _unsubscribeEvents() {
    this.subscriptions.forEach((s) => s.dispose());
  }

  async _scrollToNavItem(navItemMenuKey: string) {
    const region = await shellApi.regionManager.getRegion(shellApi.regionManager.regions.shell.navigationMenu);

    const allViews = region.currentActiveViews;

    // Extract the actual view id from the key (remove plugin prefix)
    // navItemMenuKey comes as "primaria-shell::pdf-viewer", we need just "pdf-viewer"
    const viewId = navItemMenuKey.includes("::") ? navItemMenuKey.split("::")[1] : navItemMenuKey;

    const targetView = allViews.find((view: any) => view.id === viewId);

    if (!targetView) {
      shellApi.broker.publish(BROKER_EVENTS.shell.scrollToNavItemCompleted, {
        scrollTop: 0,
        containerTop: 0,
        itemIndex: -1,
      });
      return;
    }

    // Sort views by sortHint to find the correct position
    const sortedViews = [...allViews].sort((a: any, b: any) => {
      const sortHintA = a.sortHint || "999";
      const sortHintB = b.sortHint || "999";
      return sortHintA.localeCompare(sortHintB);
    });

    const targetIndex = sortedViews.findIndex((view: any) => view.id === viewId);

    if (targetIndex === -1) {
      shellApi.broker.publish(BROKER_EVENTS.shell.scrollToNavItemCompleted, {
        scrollTop: 0,
        containerTop: 0,
        itemIndex: -1,
      });
      return;
    }

    const menuContainer = this.shadowRoot?.querySelector("#menu-region-container") as HTMLElement;
    if (!menuContainer) {
      shellApi.broker.publish(BROKER_EVENTS.shell.scrollToNavItemCompleted, {
        scrollTop: 0,
        containerTop: 0,
        itemIndex: targetIndex,
      });
      return;
    }

    const itemHeight = 51;
    const targetPosition = itemHeight * targetIndex;
    const containerHeight = menuContainer.clientHeight;

    // Scroll to position the item in the middle of the container
    const scrollPosition = targetPosition - containerHeight / 2 + itemHeight / 2;
    menuContainer.scrollTo({
      top: Math.max(0, scrollPosition),
      behavior: "smooth",
    });

    // Wait for scroll to complete and then publish the completed event
    setTimeout(() => {
      const containerRect = menuContainer.getBoundingClientRect();

      // Get all nav items from the container
      const navItems = Array.from(menuContainer.children) as HTMLElement[];

      // Find the actual DOM element for the target item
      let itemAbsoluteY = window.innerHeight / 2; // default fallback

      if (navItems[targetIndex]) {
        const itemRect = navItems[targetIndex].getBoundingClientRect();
        itemAbsoluteY = itemRect.top;
      }

      const data = {
        scrollTop: menuContainer.scrollTop,
        containerTop: containerRect.top,
        itemIndex: targetIndex,
        itemAbsoluteY: itemAbsoluteY,
      };
      shellApi.broker.publish(BROKER_EVENTS.shell.scrollToNavItemCompleted, data);
    }, 300);
  }
}
