/**
 * Services Controller
 *
 * Handles:
 * - Category collapse/expand animations
 * - Fuzzy search
 * - Content swap between list view and detail view
 * - Tab switching within detail view
 * - History API for browser back/forward navigation
 */

import Fuse from 'fuse.js';

interface ServiceItem {
  id: string;
  name: string;
  element: HTMLElement;
  categoryRow: HTMLElement;
}

export class ServicesController {
  private fuse: Fuse<ServiceItem> | null = null;
  private services: ServiceItem[] = [];
  private listView: HTMLElement | null = null;
  private detailView: HTMLElement | null = null;

  constructor() {
    this.listView = document.getElementById('services-list-view');
    this.detailView = document.getElementById('service-detail-view');

    // Only initialize if we're on the services page
    if (!this.listView) return;

    this.init();
  }

  private init(): void {
    this.setupCategoryToggle();
    this.setupSearch();
    this.setupDetailTabs();
    this.setupChevronNavigation();
    this.setupBackNavigation();
    this.setupHistoryNavigation();
    this.restoreStateFromUrl();
  }

  private setupSearch(): void {
    const searchInput = document.querySelector('swp-search-input input') as HTMLInputElement;
    if (!searchInput) return;

    // Build service index from DOM
    this.buildServiceIndex();

    // Initialize Fuse.js
    this.fuse = new Fuse(this.services, {
      keys: ['name'],
      threshold: 0.3,
      minMatchCharLength: 2
    });

    // Listen for input
    searchInput.addEventListener('input', (e) => {
      const query = (e.target as HTMLInputElement).value.trim();
      this.filterServices(query);
    });
  }

  private buildServiceIndex(): void {
    const serviceRows = document.querySelectorAll('swp-card.services-list swp-data-table-row');

    serviceRows.forEach((row) => {
      const element = row as HTMLElement;
      const id = element.getAttribute('data-service-detail') || '';
      const nameCell = element.querySelector('swp-data-table-cell:first-child');
      const name = nameCell?.textContent?.trim() || '';

      // Find the category row for this service
      let categoryRow: HTMLElement | null = null;
      let sibling = element.previousElementSibling;
      while (sibling) {
        if (sibling.tagName.toLowerCase() === 'swp-category-row') {
          categoryRow = sibling as HTMLElement;
          break;
        }
        sibling = sibling.previousElementSibling;
      }

      if (categoryRow) {
        this.services.push({
          id,
          name,
          element,
          categoryRow
        });
      }
    });
  }

  private filterServices(query: string): void {
    if (!query || query.length < 2) {
      // Show all services and categories
      this.showAll();
      return;
    }

    if (!this.fuse) return;

    // Get matching services
    const results = this.fuse.search(query);
    const matchingIds = new Set(results.map(r => r.item.id));

    // Track which categories have visible services
    const visibleCategories = new Set<HTMLElement>();

    // Show/hide services
    this.services.forEach(service => {
      if (matchingIds.has(service.id)) {
        service.element.style.display = 'grid';
        visibleCategories.add(service.categoryRow);
      } else {
        service.element.style.display = 'none';
      }
    });

    // Show/hide categories based on whether they have visible services
    const allCategoryRows = document.querySelectorAll('swp-card.services-list swp-category-row');
    allCategoryRows.forEach((row) => {
      const categoryRow = row as HTMLElement;
      if (visibleCategories.has(categoryRow)) {
        categoryRow.style.display = 'grid';
        // Ensure category is expanded when filtering
        categoryRow.setAttribute('data-expanded', 'true');
      } else {
        categoryRow.style.display = 'none';
      }
    });
  }

  private showAll(): void {
    // Show all services
    this.services.forEach(service => {
      service.element.style.display = 'grid';
    });

    // Show all categories
    const allCategoryRows = document.querySelectorAll('swp-card.services-list swp-category-row');
    allCategoryRows.forEach((row) => {
      (row as HTMLElement).style.display = 'grid';
    });
  }

  private setupCategoryToggle(): void {
    document.addEventListener('click', (e) => {
      const categoryRow = (e.target as HTMLElement).closest('swp-category-row');
      if (!categoryRow) return;

      const isExpanded = categoryRow.getAttribute('data-expanded') !== 'false';

      // Find all service rows belonging to this category
      const serviceRows = this.getServiceRowsForCategory(categoryRow);

      if (isExpanded) {
        // Collapse - set attribute immediately so chevron animates with rows
        categoryRow.setAttribute('data-expanded', 'false');
        this.collapseRows(serviceRows);
      } else {
        // Expand - set attribute immediately so chevron animates with rows
        categoryRow.setAttribute('data-expanded', 'true');
        this.expandRows(serviceRows);
      }
    });
  }

  private getServiceRowsForCategory(categoryRow: Element): HTMLElement[] {
    const rows: HTMLElement[] = [];
    let sibling = categoryRow.nextElementSibling;

    while (sibling && sibling.tagName.toLowerCase() === 'swp-data-table-row') {
      rows.push(sibling as HTMLElement);
      sibling = sibling.nextElementSibling;
    }

    return rows;
  }

  private collapseRows(rows: HTMLElement[]): void {
    if (rows.length === 0) return;

    // Animate each row
    rows.forEach((row) => {
      const height = row.offsetHeight;
      row.style.height = `${height}px`;
      row.style.overflow = 'hidden';

      // Force reflow
      row.offsetHeight;

      row.style.transition = 'height 0.2s ease, opacity 0.2s ease';
      row.style.height = '0';
      row.style.opacity = '0';
    });

    // After animation completes
    setTimeout(() => {
      rows.forEach(row => {
        row.style.display = 'none';
        row.style.height = '';
        row.style.opacity = '';
        row.style.overflow = '';
        row.style.transition = '';
      });
    }, 200);
  }

  private expandRows(rows: HTMLElement[]): void {
    rows.forEach((row) => {
      // First make visible but with 0 height
      row.style.display = 'grid';
      row.style.height = '0';
      row.style.opacity = '0';
      row.style.overflow = 'hidden';

      // Measure natural height
      row.style.height = 'auto';
      const naturalHeight = row.offsetHeight;
      row.style.height = '0';

      // Force reflow
      row.offsetHeight;

      // Animate to natural height
      row.style.transition = 'height 0.2s ease, opacity 0.2s ease';
      row.style.height = `${naturalHeight}px`;
      row.style.opacity = '1';
    });

    // Cleanup after animation
    setTimeout(() => {
      rows.forEach(row => {
        row.style.height = '';
        row.style.opacity = '';
        row.style.overflow = '';
        row.style.transition = '';
      });
    }, 200);
  }

  /**
   * Setup popstate listener for browser back/forward
   */
  private setupHistoryNavigation(): void {
    window.addEventListener('popstate', (e: PopStateEvent) => {
      if (e.state?.serviceKey) {
        this.showDetailViewInternal(e.state.serviceKey);
      } else {
        this.showListViewInternal();
      }
    });
  }

  /**
   * Restore view state from URL on page load
   */
  private restoreStateFromUrl(): void {
    const hash = window.location.hash;
    if (hash.startsWith('#service-')) {
      const serviceKey = hash.substring(1); // Remove #
      this.showDetailViewInternal(serviceKey);
    }
  }

  /**
   * Setup tab switching for the detail view
   */
  private setupDetailTabs(): void {
    if (!this.detailView) return;

    const tabs = this.detailView.querySelectorAll<HTMLElement>('swp-tab-bar > swp-tab[data-tab]');

    tabs.forEach(tab => {
      tab.addEventListener('click', () => {
        const targetTab = tab.dataset.tab;
        if (targetTab) {
          this.switchTab(this.detailView!, targetTab);
        }
      });
    });
  }

  /**
   * Switch to a specific tab within a container
   */
  private switchTab(container: HTMLElement, targetTab: string): void {
    const tabs = container.querySelectorAll<HTMLElement>('swp-tab-bar > swp-tab[data-tab]');
    const contents = container.querySelectorAll<HTMLElement>('swp-tab-content[data-tab]');

    tabs.forEach(t => {
      t.classList.toggle('active', t.dataset.tab === targetTab);
    });

    contents.forEach(content => {
      content.classList.toggle('active', content.dataset.tab === targetTab);
    });
  }

  /**
   * Setup row click to show detail view
   * Ignores clicks on category rows
   */
  private setupChevronNavigation(): void {
    document.addEventListener('click', (e: Event) => {
      const target = e.target as HTMLElement;

      // Ignore clicks on category rows
      if (target.closest('swp-category-row')) {
        return;
      }

      const row = target.closest<HTMLElement>('swp-data-table-row[data-service-detail]');

      if (row) {
        const serviceKey = row.dataset.serviceDetail;
        if (serviceKey) {
          this.showDetailView(serviceKey);
        }
      }
    });
  }

  /**
   * Setup back button to return to list view
   */
  private setupBackNavigation(): void {
    document.addEventListener('click', (e: Event) => {
      const target = e.target as HTMLElement;
      const backLink = target.closest<HTMLElement>('[data-service-back]');

      if (backLink) {
        this.showListView();
      }
    });
  }

  /**
   * Show the detail view and hide list view (with history push)
   */
  private showDetailView(serviceKey: string): void {
    // Push state to history
    history.pushState(
      { serviceKey },
      '',
      `#${serviceKey}`
    );
    this.showDetailViewInternal(serviceKey);
  }

  /**
   * Show detail view without modifying history (for popstate)
   */
  private showDetailViewInternal(serviceKey: string): void {
    if (this.listView && this.detailView) {
      // Fade out list view
      this.listView.classList.add('view-fade-out');

      // After fade, switch views
      setTimeout(() => {
        this.listView!.style.display = 'none';
        this.listView!.classList.remove('view-fade-out');

        // Show detail view with fade in
        this.detailView!.style.display = 'block';
        this.detailView!.classList.add('view-fade-out');
        this.detailView!.dataset.service = serviceKey;

        // Reset to first tab
        this.switchTab(this.detailView!, 'general');

        // Trigger fade in
        requestAnimationFrame(() => {
          this.detailView!.classList.remove('view-fade-out');
        });
      }, 100);
    }
  }

  /**
   * Show the list view and hide detail view (with history push)
   */
  private showListView(): void {
    // Push state to history (clear hash)
    history.pushState(
      {},
      '',
      window.location.pathname
    );
    this.showListViewInternal();
  }

  /**
   * Show list view without modifying history (for popstate)
   */
  private showListViewInternal(): void {
    if (this.listView && this.detailView) {
      // Fade out detail view
      this.detailView.classList.add('view-fade-out');

      // After fade, switch views
      setTimeout(() => {
        this.detailView!.style.display = 'none';
        this.detailView!.classList.remove('view-fade-out');

        // Show list view with fade in
        this.listView!.style.display = 'block';
        this.listView!.classList.add('view-fade-out');

        // Trigger fade in
        requestAnimationFrame(() => {
          this.listView!.classList.remove('view-fade-out');
        });
      }, 100);
    }
  }
}
