import * as interfaces from '../../interfaces/index.js';

import {
  DeesElement,
  type TemplateResult,
  property,
  state,
  customElement,
  html,
  css,
  cssManager,
} from '@design.estate/dees-element';

import * as domtools from '@design.estate/dees-domtools';
import { demoFunc } from './dees-appui-tabs.demo.js';
import { themeDefaultStyles } from '../../00theme.js';

@customElement('dees-appui-tabs')
export class DeesAppuiTabs extends DeesElement {
  public static demo = demoFunc;
  public static demoGroup = 'App UI';

  // INSTANCE
  @property({
    type: Array,
  })
  accessor tabs: interfaces.IMenuItem[] = [];

  @property({ type: Object })
  accessor selectedTab: interfaces.IMenuItem | null = null;

  @property({ type: Boolean })
  accessor showTabIndicator: boolean = true;

  @property({ type: String })
  accessor tabStyle: 'horizontal' | 'vertical' = 'horizontal';

  @property({ type: Boolean })
  accessor autoHide: boolean = false;

  @property({ type: Number })
  accessor autoHideThreshold: number = 0;

  // Scroll state for fade indicators
  @state()
  private accessor canScrollLeft: boolean = false;

  @state()
  private accessor canScrollRight: boolean = false;

  private resizeObserver: ResizeObserver | null = null;

  public static styles = [
    themeDefaultStyles,
    cssManager.defaultStyles,
    css`
      /* TODO: Migrate hardcoded values to --dees-* CSS variables */
      :host {
        display: block;
        position: relative;
        width: 100%;
        min-width: 0;
        overflow: hidden;
      }

      .tabs-wrapper {
        position: relative;
        min-width: 0;
      }

      .tabs-wrapper.horizontal-wrapper {
        height: 48px;
        border-bottom: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
        box-sizing: border-box;
        overflow: hidden;
      }

      /* Scroll fade indicators */
      .scroll-fade {
        position: absolute;
        top: 0;
        bottom: 1px;
        width: 48px;
        pointer-events: none;
        opacity: 0;
        transition: opacity 0.2s ease;
        z-index: 10;
      }

      .scroll-fade-left {
        left: 0;
        background: linear-gradient(to right,
          ${cssManager.bdTheme('#ffffff', '#161616')} 0%,
          ${cssManager.bdTheme('rgba(255,255,255,0)', 'rgba(22,22,22,0)')} 100%);
      }

      .scroll-fade-right {
        right: 0;
        background: linear-gradient(to left,
          ${cssManager.bdTheme('#ffffff', '#161616')} 0%,
          ${cssManager.bdTheme('rgba(255,255,255,0)', 'rgba(22,22,22,0)')} 100%);
      }

      .scroll-fade.visible {
        opacity: 1;
      }

      .tabsContainer {
        position: relative;
        user-select: none;
        min-width: 0;
      }

      .tabsContainer.horizontal {
        display: flex;
        align-items: center;
        font-size: 14px;
        overflow-x: auto;
        overflow-y: hidden;
        overscroll-behavior: contain;
        scrollbar-width: thin;
        scrollbar-color: transparent transparent;
        height: 100%;
        padding: 0 16px;
        gap: 4px;
      }

      /* Show scrollbar on hover */
      .tabs-wrapper:hover .tabsContainer.horizontal {
        scrollbar-color: ${cssManager.bdTheme('rgba(0,0,0,0.2)', 'rgba(255,255,255,0.2)')} transparent;
      }

      .tabsContainer.horizontal::-webkit-scrollbar {
        height: 4px;
      }

      .tabsContainer.horizontal::-webkit-scrollbar-track {
        background: transparent;
      }

      .tabsContainer.horizontal::-webkit-scrollbar-thumb {
        background: transparent;
        border-radius: 2px;
        transition: background 0.2s ease;
      }

      .tabs-wrapper:hover .tabsContainer.horizontal::-webkit-scrollbar-thumb {
        background: ${cssManager.bdTheme('rgba(0,0,0,0.2)', 'rgba(255,255,255,0.2)')};
      }

      .tabs-wrapper:hover .tabsContainer.horizontal::-webkit-scrollbar-thumb:hover {
        background: ${cssManager.bdTheme('rgba(0,0,0,0.35)', 'rgba(255,255,255,0.35)')};
      }

      .tabsContainer.vertical {
        display: flex;
        flex-direction: column;
        padding: 8px;
        font-size: 14px;
        gap: 2px;
        position: relative;
        background: ${cssManager.bdTheme('#f9fafb', '#18181b')};
        border-radius: 8px;
      }

      .tab {
        color: ${cssManager.bdTheme('#71717a', '#71717a')};
        white-space: nowrap;
        cursor: pointer;
        transition: color 0.15s ease;
        font-weight: 500;
        position: relative;
        z-index: 2;
      }

      .horizontal .tab {
        padding: 0 16px;
        height: 100%;
        display: inline-flex;
        align-items: center;
        gap: 8px;
        position: relative;
        border-radius: 6px 6px 0 0;
        transition: background-color 0.15s ease;
      }
      
      .horizontal .tab:not(:last-child)::after {
        content: '';
        position: absolute;
        right: -2px;
        top: 50%;
        transform: translateY(-50%);
        height: 20px;
        width: 1px;
        background: ${cssManager.bdTheme('#e5e7eb', '#27272a')};
        opacity: 0.5;
      }
      
      .horizontal .tab .tab-content {
        display: inline-flex;
        align-items: center;
        gap: 8px;
      }

      .vertical .tab {
        padding: 10px 16px;
        border-radius: 6px;
        width: 100%;
        display: flex;
        align-items: center;
        gap: 8px;
        transition: all 0.15s ease;
      }

      .tab:hover {
        color: ${cssManager.bdTheme('#09090b', '#fafafa')};
      }
      
      .horizontal .tab:hover {
        background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.03)', 'rgba(255, 255, 255, 0.03)')};
      }
      
      .horizontal .tab:hover::after,
      .horizontal .tab:hover + .tab::after {
        opacity: 0;
      }

      .vertical .tab:hover {
        background: ${cssManager.bdTheme('rgba(244, 244, 245, 0.5)', 'rgba(39, 39, 42, 0.5)')};
      }

      .horizontal .tab.selectedTab {
        color: ${cssManager.bdTheme('#09090b', '#fafafa')};
      }
      
      .horizontal .tab.selectedTab::after,
      .horizontal .tab.selectedTab + .tab::after {
        opacity: 0;
      }

      .vertical .tab.selectedTab {
        color: ${cssManager.bdTheme('#09090b', '#fafafa')};
      }

      .tab dees-icon {
        font-size: 16px;
      }

      .tabIndicator {
        position: absolute;
        transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        opacity: 0;
      }
      
      .tabIndicator.no-transition {
        transition: none;
      }

      .tabs-wrapper .tabIndicator {
        height: 3px;
        bottom: 0;
        background: ${cssManager.bdTheme('#3b82f6', '#3b82f6')};
        border-radius: 3px 3px 0 0;
        z-index: 3;
      }

      .vertical-wrapper {
        position: relative;
      }

      .vertical-wrapper .tabIndicator {
        left: 8px;
        right: 8px;
        border-radius: 6px;
        background: ${cssManager.bdTheme('#ffffff', '#27272a')};
        z-index: 1;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
      }

      /* Close button */
      .tab-close {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 16px;
        height: 16px;
        border-radius: 4px;
        margin-left: 8px;
        opacity: 0.4;
        transition: opacity 0.15s, background 0.15s;
        color: ${cssManager.bdTheme('#71717a', '#71717a')};
      }

      .tab:hover .tab-close {
        opacity: 0.7;
      }

      .tab-close:hover {
        opacity: 1;
        background: ${cssManager.bdTheme('rgba(0,0,0,0.1)', 'rgba(255,255,255,0.1)')};
        color: ${cssManager.bdTheme('#ef4444', '#f87171')};
      }

      .tab.selectedTab .tab-close {
        opacity: 0.5;
      }

      .tab.selectedTab:hover .tab-close {
        opacity: 0.8;
      }

      .tab.selectedTab .tab-close:hover {
        opacity: 1;
      }
    `,
  ];

  public render(): TemplateResult {
    // Auto-hide when enabled and tab count is at or below threshold
    if (this.autoHide && this.tabs.length <= this.autoHideThreshold) {
      return html``;
    }
    return html`
      ${this.renderTabsWrapper()}
    `;
  }

  private renderTabsWrapper(): TemplateResult {
    const isHorizontal = this.tabStyle === 'horizontal';
    const wrapperClass = isHorizontal ? 'tabs-wrapper horizontal-wrapper' : 'vertical-wrapper';
    const containerClass = `tabsContainer ${this.tabStyle}`;

    if (isHorizontal) {
      return html`
        <div class="${wrapperClass}">
          <div class="scroll-fade scroll-fade-left ${this.canScrollLeft ? 'visible' : ''}"></div>
          <div class="${containerClass}" @scroll=${this.handleScroll}>
            ${this.tabs.map(tab => this.renderTab(tab, isHorizontal))}
          </div>
          <div class="scroll-fade scroll-fade-right ${this.canScrollRight ? 'visible' : ''}"></div>
          ${this.showTabIndicator ? html`<div class="tabIndicator"></div>` : ''}
        </div>
      `;
    }

    return html`
      <div class="${wrapperClass}">
        <div class="${containerClass}">
          ${this.tabs.map(tab => this.renderTab(tab, isHorizontal))}
        </div>
        ${this.showTabIndicator ? html`<div class="tabIndicator"></div>` : ''}
      </div>
    `;
  }

  private renderTab(tab: interfaces.IMenuItem, isHorizontal: boolean): TemplateResult {
    const isSelected = tab === this.selectedTab;
    const classes = `tab ${isSelected ? 'selectedTab' : ''}`;

    const closeButton = tab.closeable ? html`
      <span class="tab-close" @click="${(e: Event) => this.closeTab(e, tab)}">
        <dees-icon .icon=${'lucide:x'} style="font-size: 12px;"></dees-icon>
      </span>
    ` : '';

    const content = isHorizontal ? html`
      <span class="tab-content">
        ${this.renderTabIcon(tab)}
        ${tab.key}
      </span>
      ${closeButton}
    ` : html`
      ${this.renderTabIcon(tab)}
      ${tab.key}
      ${closeButton}
    `;

    return html`
      <div
        class="${classes}"
        @click="${() => this.selectTab(tab)}"
      >
        ${content}
      </div>
    `;
  }

  private renderTabIcon(tab: interfaces.IMenuItem): TemplateResult | '' {
    return tab.iconName ? html`<dees-icon .icon=${tab.iconName}></dees-icon>` : '';
  }

  private selectTab(tabArg: interfaces.IMenuItem) {
    this.selectedTab = tabArg;
    tabArg.action();

    // Scroll selected tab into view
    requestAnimationFrame(() => {
      this.scrollTabIntoView(tabArg);
    });

    // Emit tab-select event
    this.dispatchEvent(new CustomEvent('tab-select', {
      detail: { tab: tabArg },
      bubbles: true,
      composed: true
    }));
  }

  private closeTab(e: Event, tab: interfaces.IMenuItem) {
    e.stopPropagation();  // Don't select tab when closing

    // Call the tab's onClose callback if defined
    if (tab.onClose) {
      tab.onClose();
    }

    // Also emit event for parent components
    this.dispatchEvent(new CustomEvent('tab-close', {
      detail: { tab },
      bubbles: true,
      composed: true
    }));
  }

  firstUpdated() {
    if (this.tabs && this.tabs.length > 0) {
      this.selectTab(this.tabs[0]);
    }

    // Set up ResizeObserver for scroll state updates
    this.setupResizeObserver();

    // Initial scroll state check
    requestAnimationFrame(() => {
      this.updateScrollState();
    });
  }

  async disconnectedCallback() {
    await super.disconnectedCallback();
    if (this.resizeObserver) {
      this.resizeObserver.disconnect();
      this.resizeObserver = null;
    }
  }

  private setupResizeObserver() {
    if (this.tabStyle !== 'horizontal') return;

    this.resizeObserver = new ResizeObserver(() => {
      this.updateScrollState();
    });

    const container = this.shadowRoot?.querySelector('.tabsContainer.horizontal');
    if (container) {
      this.resizeObserver.observe(container);
    }
  }

  private handleScroll = () => {
    this.updateScrollState();
  };

  private updateScrollState() {
    const container = this.shadowRoot?.querySelector('.tabsContainer.horizontal') as HTMLElement;
    if (!container) return;

    const scrollLeft = container.scrollLeft;
    const scrollWidth = container.scrollWidth;
    const clientWidth = container.clientWidth;

    // Small threshold to account for rounding
    const threshold = 2;

    this.canScrollLeft = scrollLeft > threshold;
    this.canScrollRight = scrollLeft < scrollWidth - clientWidth - threshold;
  }

  private scrollTabIntoView(tab: interfaces.IMenuItem) {
    if (this.tabStyle !== 'horizontal') return;

    const tabIndex = this.tabs.indexOf(tab);
    if (tabIndex === -1) return;

    const container = this.shadowRoot?.querySelector('.tabsContainer.horizontal') as HTMLElement;
    const tabElement = container?.querySelector(`.tab:nth-child(${tabIndex + 1})`) as HTMLElement;

    if (tabElement && container) {
      const containerRect = container.getBoundingClientRect();
      const tabRect = tabElement.getBoundingClientRect();

      // Check if tab is fully visible
      const isFullyVisible =
        tabRect.left >= containerRect.left &&
        tabRect.right <= containerRect.right;

      if (!isFullyVisible) {
        tabElement.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });
      }
    }
  }

  async updated(changedProperties: Map<string, any>) {
    super.updated(changedProperties);

    if (changedProperties.has('tabs') && this.tabs && this.tabs.length > 0 && !this.selectedTab) {
      this.selectTab(this.tabs[0]);
    }

    if (changedProperties.has('selectedTab') || changedProperties.has('tabs')) {
      await this.updateComplete;
      // Wait for fonts to load on first update
      if (!this.indicatorInitialized && document.fonts) {
        await document.fonts.ready;
      }
      requestAnimationFrame(() => {
        this.updateTabIndicator();
        this.updateScrollState();
      });
    }
  }

  private indicatorInitialized = false;

  private updateTabIndicator() {
    if (!this.shouldShowIndicator()) return;

    const selectedTabElement = this.getSelectedTabElement();
    if (!selectedTabElement) return;

    const indicator = this.getIndicatorElement();
    if (!indicator) return;

    this.handleInitialTransition(indicator);
    
    if (this.tabStyle === 'horizontal') {
      this.updateHorizontalIndicator(indicator, selectedTabElement);
    } else {
      this.updateVerticalIndicator(indicator, selectedTabElement);
    }

    indicator.style.opacity = '1';
  }

  private shouldShowIndicator(): boolean {
    return this.selectedTab && this.showTabIndicator && this.tabs.includes(this.selectedTab);
  }

  private getSelectedTabElement(): HTMLElement | null {
    const selectedIndex = this.tabs.indexOf(this.selectedTab);
    const isHorizontal = this.tabStyle === 'horizontal';
    const selector = isHorizontal 
      ? `.tabs-wrapper .tabsContainer .tab:nth-child(${selectedIndex + 1})`
      : `.vertical-wrapper .tabsContainer .tab:nth-child(${selectedIndex + 1})`;
      
    return this.shadowRoot.querySelector(selector);
  }

  private getIndicatorElement(): HTMLElement | null {
    return this.shadowRoot.querySelector('.tabIndicator');
  }

  private handleInitialTransition(indicator: HTMLElement): void {
    if (!this.indicatorInitialized) {
      indicator.classList.add('no-transition');
      this.indicatorInitialized = true;
      
      setTimeout(() => {
        indicator.classList.remove('no-transition');
      }, 50);
    }
  }

  private updateHorizontalIndicator(indicator: HTMLElement, tabElement: HTMLElement): void {
    const tabContent = tabElement.querySelector('.tab-content') as HTMLElement;
    if (!tabContent) return;

    const wrapperRect = indicator.parentElement.getBoundingClientRect();
    const contentRect = tabContent.getBoundingClientRect();
    
    const contentLeft = contentRect.left - wrapperRect.left;
    const indicatorWidth = contentRect.width + 8;
    const indicatorLeft = contentLeft - 4;
    
    indicator.style.width = `${indicatorWidth}px`;
    indicator.style.left = `${indicatorLeft}px`;
  }

  private updateVerticalIndicator(indicator: HTMLElement, tabElement: HTMLElement): void {
    const tabsContainer = this.shadowRoot.querySelector('.vertical-wrapper .tabsContainer') as HTMLElement;
    if (!tabsContainer) return;
    
    indicator.style.top = `${tabElement.offsetTop + tabsContainer.offsetTop}px`;
    indicator.style.height = `${tabElement.clientHeight}px`;
  }
}