import { Component, ChangeDetectionStrategy, signal, computed } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { FilterConfig, SortConfig, GroupByResult } from '../../../../../ui-data-utils/src/lib/types';
import { sortBy, sortByMultiple } from '../../../../../ui-data-utils/src/lib/sorting';
import { filterBy, filterByMultiple, searchFilter } from '../../../../../ui-data-utils/src/lib/filtering';
import { getPaginationRange, paginate } from '../../../../../ui-data-utils/src/lib/pagination';
import { aggregate, groupBy, pivot, pluck, unique } from '../../../../../ui-data-utils/src/lib/transformation';


interface SampleData {
  id: number;
  name: string;
  department: string;
  salary: number;
  hireDate: string;
  active: boolean;
  skills: string[];
}

@Component({
  selector: 'ui-data-utils-demo',
  standalone: true,
  imports: [CommonModule, FormsModule],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <div style="padding: 2rem;">
      <h2>UI Data Utils Demo</h2>
      <p>Comprehensive demonstration of data manipulation utilities</p>

      <!-- Sample Data Display -->
      <section style="margin-bottom: 3rem;">
        <h3>Sample Employee Data ({{ sampleData.length }} records)</h3>
        <div style="background: #f8f9fa; padding: 1rem; border-radius: 4px; margin-bottom: 1rem;">
          <h4>Raw Data Preview:</h4>
          <pre style="max-height: 200px; overflow-y: auto;">{{ getSampleDataPreview() }}</pre>
        </div>
      </section>

      <!-- Sorting Utilities Demo -->
      <section style="margin-bottom: 3rem;">
        <h3>🔄 Sorting Utilities</h3>
        
        <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 2rem;">
          <!-- Single Sort -->
          <div>
            <h4>Single Property Sort</h4>
            <div style="margin-bottom: 1rem;">
              <label>Sort by: </label>
              <select [(ngModel)]="sortField" (ngModelChange)="applySingleSort()">
                <option value="name">Name</option>
                <option value="department">Department</option>
                <option value="salary">Salary</option>
                <option value="hireDate">Hire Date</option>
              </select>
              <label style="margin-left: 1rem;">
                <input type="checkbox" [(ngModel)]="sortDesc" (ngModelChange)="applySingleSort()">
                Descending
              </label>
            </div>
            <div style="background: #e3f2fd; padding: 1rem; border-radius: 4px; max-height: 200px; overflow-y: auto;">
              <pre>{{ getSortedDataPreview() }}</pre>
            </div>
          </div>

          <!-- Multi-column Sort -->
          <div>
            <h4>Multi-column Sort</h4>
            <p style="font-size: 0.9em; color: #666;">Department → Salary → Name</p>
            <div style="background: #e8f5e8; padding: 1rem; border-radius: 4px; max-height: 200px; overflow-y: auto;">
              <pre>{{ getMultiSortedDataPreview() }}</pre>
            </div>
          </div>
        </div>
      </section>

      <!-- Filtering Utilities Demo -->
      <section style="margin-bottom: 3rem;">
        <h3>🔍 Filtering Utilities</h3>
        
        <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 2rem;">
          <!-- Search Filter -->
          <div>
            <h4>Search Filter</h4>
            <input 
              type="text" 
              placeholder="Search in name, department..."
              [(ngModel)]="searchTerm"
              (ngModelChange)="applySearchFilter()"
              style="width: 100%; padding: 0.5rem; margin-bottom: 1rem;"
            >
            <div style="background: #fff3cd; padding: 1rem; border-radius: 4px; max-height: 200px; overflow-y: auto;">
              <pre>{{ getSearchFilteredDataPreview() }}</pre>
            </div>
          </div>

          <!-- Property Filter -->
          <div>
            <h4>Property Filters</h4>
            <div style="margin-bottom: 1rem;">
              <label>Department: </label>
              <select [(ngModel)]="filterDepartment" (ngModelChange)="applyPropertyFilter()">
                <option value="">All Departments</option>
                <option value="Engineering">Engineering</option>
                <option value="Marketing">Marketing</option>
                <option value="Sales">Sales</option>
                <option value="HR">HR</option>
              </select>
            </div>
            <div style="margin-bottom: 1rem;">
              <label>Min Salary: </label>
              <input 
                type="number" 
                [(ngModel)]="minSalary" 
                (ngModelChange)="applyPropertyFilter()"
                placeholder="50000"
                style="width: 120px; padding: 0.25rem;"
              >
            </div>
            <div style="background: #f3e5f5; padding: 1rem; border-radius: 4px; max-height: 200px; overflow-y: auto;">
              <pre>{{ getPropertyFilteredDataPreview() }}</pre>
            </div>
          </div>
        </div>
      </section>

      <!-- Pagination Demo -->
      <section style="margin-bottom: 3rem;">
        <h3>📄 Pagination Utilities</h3>
        
        <div>
          <div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem;">
            <label>Page Size: </label>
            <select [(ngModel)]="pageSize" (ngModelChange)="updatePagination()">
              <option [value]="3">3</option>
              <option [value]="5">5</option>
              <option [value]="7">7</option>
              <option [value]="10">10</option>
            </select>
            
            <label>Page: </label>
            <input 
              type="number" 
              [(ngModel)]="currentPage" 
              (ngModelChange)="updatePagination()"
              [min]="1" 
              [max]="paginationResult().totalPages"
              style="width: 60px; padding: 0.25rem;"
            >
            
            <span>of {{ paginationResult().totalPages }}</span>
            
            <button 
              (click)="previousPage()" 
              [disabled]="!paginationResult().hasPrevious"
              style="padding: 0.25rem 0.5rem;"
            >
              Previous
            </button>
            <button 
              (click)="nextPage()" 
              [disabled]="!paginationResult().hasNext"
              style="padding: 0.25rem 0.5rem;"
            >
              Next
            </button>
          </div>
          
          <div style="margin-bottom: 1rem;">
            <strong>Page Navigation: </strong>
            @for (page of pageRange(); track page) {
              @if (page === 'ellipsis') {
                <span style="margin: 0 0.5rem;">...</span>
              } @else {
                <button 
                  (click)="goToPage(page)"
                  [style.font-weight]="page === currentPage() ? 'bold' : 'normal'"
                  [style.background]="page === currentPage() ? '#007bff' : '#f8f9fa'"
                  [style.color]="page === currentPage() ? 'white' : 'black'"
                  style="padding: 0.25rem 0.5rem; margin: 0 0.125rem; border: 1px solid #ccc; cursor: pointer;"
                >
                  {{ page }}
                </button>
              }
            }
          </div>
          
          <div style="background: #e1f5fe; padding: 1rem; border-radius: 4px;">
            <p><strong>Showing:</strong> {{ getItemRangeText() }}</p>
            <pre style="max-height: 150px; overflow-y: auto;">{{ getPaginatedDataPreview() }}</pre>
          </div>
        </div>
      </section>

      <!-- Transformation Utilities Demo -->
      <section style="margin-bottom: 3rem;">
        <h3>🔄 Transformation Utilities</h3>
        
        <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 2rem;">
          <!-- Group By -->
          <div>
            <h4>Group By Department</h4>
            <div style="background: #f1f8e9; padding: 1rem; border-radius: 4px; max-height: 200px; overflow-y: auto;">
              <pre>{{ getGroupedDataPreview() }}</pre>
            </div>
          </div>

          <!-- Aggregation -->
          <div>
            <h4>Salary Statistics by Department</h4>
            <div style="background: #fce4ec; padding: 1rem; border-radius: 4px; max-height: 200px; overflow-y: auto;">
              <pre>{{ getAggregationPreview() }}</pre>
            </div>
          </div>

          <!-- Pluck -->
          <div>
            <h4>Extract Names & Salaries</h4>
            <div style="background: #f3e5f5; padding: 1rem; border-radius: 4px; max-height: 200px; overflow-y: auto;">
              <pre>{{ getPluckedDataPreview() }}</pre>
            </div>
          </div>

          <!-- Pivot Table -->
          <div>
            <h4>Pivot: Department vs Active Status</h4>
            <div style="background: #fff3e0; padding: 1rem; border-radius: 4px; max-height: 200px; overflow-y: auto;">
              <pre>{{ getPivotDataPreview() }}</pre>
            </div>
          </div>
        </div>
      </section>

      <!-- Combined Operations Demo -->
      <section style="margin-bottom: 3rem;">
        <h3>🔄 Combined Operations</h3>
        <p>Demonstrate chaining multiple operations: Filter → Sort → Paginate</p>
        
        <div style="display: flex; gap: 1rem; margin-bottom: 1rem; flex-wrap: wrap;">
          <label>
            Filter Active:
            <select [(ngModel)]="combinedActiveFilter" (ngModelChange)="updateCombinedDemo()">
              <option value="">All</option>
              <option value="true">Active Only</option>
              <option value="false">Inactive Only</option>
            </select>
          </label>
          
          <label>
            Sort By:
            <select [(ngModel)]="combinedSortField" (ngModelChange)="updateCombinedDemo()">
              <option value="name">Name</option>
              <option value="salary">Salary</option>
              <option value="hireDate">Hire Date</option>
            </select>
          </label>
          
          <label>
            <input type="checkbox" [(ngModel)]="combinedSortDesc" (ngModelChange)="updateCombinedDemo()">
            Descending
          </label>
        </div>
        
        <div style="background: #e8f5e8; padding: 1rem; border-radius: 4px;">
          <p><strong>Pipeline:</strong> 
            {{ sampleData.length }} records → 
            {{ combinedFiltered().length }} filtered → 
            {{ combinedSorted().length }} sorted → 
            {{ combinedPaginated().data.length }} on page {{ combinedPaginated().page }}
          </p>
          <pre style="max-height: 200px; overflow-y: auto;">{{ getCombinedResultPreview() }}</pre>
        </div>
      </section>

      <!-- Performance Metrics -->
      <section style="margin-bottom: 3rem;">
        <h3>📊 Performance & Statistics</h3>
        
        <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem;">
          <div style="background: #f8f9fa; padding: 1rem; border-radius: 4px; text-align: center;">
            <h4>Total Records</h4>
            <div style="font-size: 2rem; font-weight: bold; color: #007bff;">{{ sampleData.length }}</div>
          </div>
          
          <div style="background: #f8f9fa; padding: 1rem; border-radius: 4px; text-align: center;">
            <h4>Departments</h4>
            <div style="font-size: 2rem; font-weight: bold; color: #28a745;">{{ getDepartmentCount() }}</div>
          </div>
          
          <div style="background: #f8f9fa; padding: 1rem; border-radius: 4px; text-align: center;">
            <h4>Avg Salary</h4>
            <div style="font-size: 2rem; font-weight: bold; color: #ffc107;">{{ getAverageSalary() }}</div>
          </div>
          
          <div style="background: #f8f9fa; padding: 1rem; border-radius: 4px; text-align: center;">
            <h4>Active Employees</h4>
            <div style="font-size: 2rem; font-weight: bold; color: #17a2b8;">{{ getActiveCount() }}%</div>
          </div>
        </div>
      </section>

      <!-- Code Examples -->
      <section style="margin-bottom: 3rem;">
        <h3>💻 Code Examples</h3>
        <div style="background: #f8f9fa; padding: 1rem; border-radius: 4px;">
          
          <h4>Sorting Examples:</h4>
          <pre style="background: #fff; padding: 1rem; border-radius: 4px; overflow-x: auto;"><code>// Single sort
const sorted = sortBy(data, {{ '{' }} key: 'salary', direction: 'desc', dataType: 'number' {{ '}' }});

// Multi-column sort  
const multiSorted = sortByMultiple(data, {{ '{' }}
  sorts: [
    {{ '{' }} key: 'department', direction: 'asc', dataType: 'string' {{ '}' }},
    {{ '{' }} key: 'salary', direction: 'desc', dataType: 'number' {{ '}' }}
  ]
{{ '}' }});</code></pre>

          <h4>Filtering Examples:</h4>
          <pre style="background: #fff; padding: 1rem; border-radius: 4px; overflow-x: auto;"><code>// Property filter
const filtered = filterBy(data, {{ '{' }}
  key: 'salary',
  operator: 'greater_than',
  value: 50000,
  dataType: 'number'
{{ '}' }});

// Search across multiple properties
const searched = searchFilter(data, 'engineer', ['name', 'department']);</code></pre>

          <h4>Pagination Examples:</h4>
          <pre style="background: #fff; padding: 1rem; border-radius: 4px; overflow-x: auto;"><code>// Paginate data
const paginatedResult = paginate(data, {{ '{' }} page: 1, pageSize: 10 {{ '}' }});

// Get page range for UI
const range = getPaginationRange(currentPage, totalPages, 7);</code></pre>

          <h4>Transformation Examples:</h4>
          <pre style="background: #fff; padding: 1rem; border-radius: 4px; overflow-x: auto;"><code>// Group by property
const groups = groupBy(data, 'department');

// Aggregate values
const stats = aggregate(data, 'salary', ['sum', 'avg', 'min', 'max']);

// Extract specific properties
const names = pluck(data, ['name', 'salary']);</code></pre>
        </div>
      </section>

      <!-- Library Info -->
      <section style="margin-bottom: 3rem;">
        <h3>📚 Library Information</h3>
        <div style="background: #e3f2fd; padding: 1.5rem; border-radius: 4px;">
          <h4>UI Data Utils Features:</h4>
          <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1rem;">
            <div>
              <h5>🔄 Sorting</h5>
              <ul style="margin: 0; padding-left: 1.5rem;">
                <li>Single & multi-column sorting</li>
                <li>Type-aware comparisons</li>
                <li>Stable sort algorithms</li>
                <li>Custom comparator functions</li>
              </ul>
            </div>
            <div>
              <h5>🔍 Filtering</h5>
              <ul style="margin: 0; padding-left: 1.5rem;">
                <li>Multiple filter operators</li>
                <li>Search across properties</li>
                <li>Complex filter combinations</li>
                <li>Type-specific filtering</li>
              </ul>
            </div>
            <div>
              <h5>📄 Pagination</h5>
              <ul style="margin: 0; padding-left: 1.5rem;">
                <li>Client-side pagination</li>
                <li>Page range calculations</li>
                <li>Pagination metadata</li>
                <li>Navigation utilities</li>
              </ul>
            </div>
            <div>
              <h5>🔄 Transformation</h5>
              <ul style="margin: 0; padding-left: 1.5rem;">
                <li>Group by operations</li>
                <li>Data aggregations</li>
                <li>Property extraction</li>
                <li>Pivot tables</li>
              </ul>
            </div>
          </div>
        </div>
      </section>
    </div>
  `,
  styles: [`
    h2 {
      color: hsl(279, 14%, 11%);
      font-size: 2rem;
      margin-bottom: 1rem;
      border-bottom: 2px solid hsl(258, 100%, 47%);
      padding-bottom: 0.5rem;
    }
    
    h3 {
      color: hsl(279, 14%, 25%);
      font-size: 1.5rem;
      margin-bottom: 1rem;
    }
    
    h4 {
      color: hsl(279, 14%, 35%);
      font-size: 1.2rem;
      margin-bottom: 0.5rem;
    }
    
    h5 {
      color: hsl(279, 14%, 45%);
      font-size: 1rem;
      margin-bottom: 0.5rem;
    }
    
    section {
      border: 1px solid #e9ecef;
      padding: 1.5rem;
      border-radius: 8px;
      background: #ffffff;
    }
    
    pre {
      margin: 0;
      font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
      font-size: 0.85rem;
      line-height: 1.4;
    }
    
    code {
      color: hsl(279, 14%, 15%);
    }
    
    button:hover:not(:disabled) {
      opacity: 0.8;
    }
    
    button:disabled {
      opacity: 0.5;
      cursor: not-allowed;
    }
    
    input, select {
      border: 1px solid #ccc;
      border-radius: 4px;
      padding: 0.25rem;
    }
    
    label {
      font-weight: 500;
    }
  `]
})
export class DataUtilsDemoComponent {
  // Sample data
  sampleData: SampleData[] = [
    { id: 1, name: 'Alice Johnson', department: 'Engineering', salary: 95000, hireDate: '2022-01-15', active: true, skills: ['JavaScript', 'Angular', 'TypeScript'] },
    { id: 2, name: 'Bob Smith', department: 'Marketing', salary: 65000, hireDate: '2021-03-22', active: true, skills: ['SEO', 'Content Marketing'] },
    { id: 3, name: 'Charlie Brown', department: 'Engineering', salary: 87000, hireDate: '2023-02-10', active: false, skills: ['React', 'Node.js'] },
    { id: 4, name: 'Diana Davis', department: 'Sales', salary: 72000, hireDate: '2020-11-05', active: true, skills: ['CRM', 'Negotiation'] },
    { id: 5, name: 'Eve Wilson', department: 'Engineering', salary: 102000, hireDate: '2021-08-18', active: true, skills: ['Python', 'Machine Learning'] },
    { id: 6, name: 'Frank Miller', department: 'HR', salary: 58000, hireDate: '2022-05-30', active: false, skills: ['Recruiting', 'Employee Relations'] },
    { id: 7, name: 'Grace Lee', department: 'Marketing', salary: 69000, hireDate: '2023-01-12', active: true, skills: ['Brand Management', 'Social Media'] },
    { id: 8, name: 'Henry Taylor', department: 'Sales', salary: 78000, hireDate: '2021-12-03', active: true, skills: ['Sales Strategy', 'Lead Generation'] },
    { id: 9, name: 'Ivy Chen', department: 'Engineering', salary: 91000, hireDate: '2022-09-14', active: true, skills: ['Vue.js', 'GraphQL'] },
    { id: 10, name: 'Jack White', department: 'HR', salary: 62000, hireDate: '2020-04-25', active: false, skills: ['Payroll', 'Benefits Administration'] }
  ];

  // Sorting controls
  sortField = signal<keyof SampleData>('name');
  sortDesc = signal<boolean>(false);

  // Filtering controls  
  searchTerm = signal<string>('');
  filterDepartment = signal<string>('');
  minSalary = signal<number | null>(null);

  // Pagination controls
  currentPage = signal<number>(1);
  pageSize = signal<number>(5);

  // Combined demo controls
  combinedActiveFilter = signal<string>('');
  combinedSortField = signal<keyof SampleData>('name');
  combinedSortDesc = signal<boolean>(false);

  // Computed data
  sortedData = computed(() => {
    const config: SortConfig<SampleData> = {
      key: this.sortField(),
      direction: this.sortDesc() ? 'desc' : 'asc',
      dataType: this.getDataType(this.sortField())
    };
    return sortBy(this.sampleData, config);
  });

  multiSortedData = computed(() => {
    return sortByMultiple(this.sampleData, {
      sorts: [
        { key: 'department', direction: 'asc', dataType: 'string' },
        { key: 'salary', direction: 'desc', dataType: 'number' },
        { key: 'name', direction: 'asc', dataType: 'string' }
      ]
    });
  });

  searchFilteredData = computed(() => {
    if (!this.searchTerm()) return this.sampleData;
    return searchFilter(this.sampleData, this.searchTerm(), ['name', 'department']);
  });

  propertyFilteredData = computed(() => {
    let filtered = this.sampleData;

    const filters: FilterConfig<SampleData>[] = [];
    
    if (this.filterDepartment()) {
      filters.push({
        key: 'department',
        operator: 'equals',
        value: this.filterDepartment(),
        dataType: 'string'
      });
    }

    if (this.minSalary() !== null) {
      filters.push({
        key: 'salary',
        operator: 'greater_than_equal',
        value: this.minSalary(),
        dataType: 'number'
      });
    }

    return filters.length > 0 ? filterByMultiple(filtered, filters) : filtered;
  });

  paginationResult = computed(() => {
    return paginate(this.sampleData, {
      page: this.currentPage(),
      pageSize: this.pageSize()
    });
  });

  pageRange = computed(() => {
    return getPaginationRange(this.currentPage(), this.paginationResult().totalPages, 7);
  });

  // Combined operations
  combinedFiltered = computed(() => {
    if (!this.combinedActiveFilter()) return this.sampleData;
    return filterBy(this.sampleData, {
      key: 'active',
      operator: 'equals',
      value: this.combinedActiveFilter() === 'true',
      dataType: 'boolean'
    });
  });

  combinedSorted = computed(() => {
    return sortBy(this.combinedFiltered(), {
      key: this.combinedSortField(),
      direction: this.combinedSortDesc() ? 'desc' : 'asc',
      dataType: this.getDataType(this.combinedSortField())
    });
  });

  combinedPaginated = computed(() => {
    return paginate(this.combinedSorted(), { page: 1, pageSize: 5 });
  });

  // Helper methods
  private getDataType(key: keyof SampleData): 'string' | 'number' | 'date' | 'boolean' {
    switch (key) {
      case 'salary': case 'id': return 'number';
      case 'hireDate': return 'date';
      case 'active': return 'boolean';
      default: return 'string';
    }
  }

  getSampleDataPreview(): string {
    return JSON.stringify(this.sampleData.slice(0, 3), null, 2);
  }

  getSortedDataPreview(): string {
    return JSON.stringify(this.sortedData().slice(0, 3).map((item: SampleData) => ({ name: item.name, [this.sortField()]: item[this.sortField()] })), null, 2);
  }

  getMultiSortedDataPreview(): string {
    return JSON.stringify(this.multiSortedData().slice(0, 4).map((item: SampleData) => ({ 
      name: item.name, 
      department: item.department, 
      salary: item.salary 
    })), null, 2);
  }

  getSearchFilteredDataPreview(): string {
    return JSON.stringify(this.searchFilteredData().slice(0, 3).map((item: SampleData) => ({ 
      name: item.name, 
      department: item.department 
    })), null, 2);
  }

  getPropertyFilteredDataPreview(): string {
    return JSON.stringify(this.propertyFilteredData().slice(0, 3).map((item: SampleData) => ({ 
      name: item.name, 
      department: item.department, 
      salary: item.salary 
    })), null, 2);
  }

  getPaginatedDataPreview(): string {
    return JSON.stringify(this.paginationResult().data.map((item: SampleData) => ({ 
      name: item.name, 
      department: item.department 
    })), null, 2);
  }

  getGroupedDataPreview(): string {
    const grouped = groupBy(this.sampleData, 'department');
    return JSON.stringify(grouped.map((group: GroupByResult<SampleData>) => ({ 
      department: group.key, 
      count: group.count,
      employees: group.items.map((emp: SampleData) => emp.name)
    })), null, 2);
  }

  getAggregationPreview(): string {
    const grouped = groupBy(this.sampleData, 'department');
    const result = grouped.map((group: GroupByResult<SampleData>) => ({
      department: group.key,
      ...aggregate(group.items, 'salary', ['sum', 'avg', 'min', 'max', 'count'])
    }));
    return JSON.stringify(result, null, 2);
  }

  getPluckedDataPreview(): string {
    const plucked = pluck(this.sampleData, ['name', 'salary']);
    return JSON.stringify(plucked.slice(0, 5), null, 2);
  }

  getPivotDataPreview(): string {
    const pivotData = this.sampleData.map(emp => ({
      department: emp.department,
      status: emp.active ? 'Active' : 'Inactive',
      count: 1
    }));
    
    const pivotResult = pivot(pivotData, 'department', 'status', 'count', 'sum');
    return JSON.stringify(pivotResult, null, 2);
  }

  getCombinedResultPreview(): string {
    return JSON.stringify(this.combinedPaginated().data.map((item: SampleData) => ({ 
      name: item.name, 
      department: item.department,
      salary: item.salary,
      active: item.active
    })), null, 2);
  }

  getItemRangeText(): string {
    const result = this.paginationResult();
    if (result.totalItems === 0) return '0 of 0';
    return `${result.startIndex + 1}-${result.endIndex + 1} of ${result.totalItems}`;
  }

  getDepartmentCount(): number {
    return unique(this.sampleData, 'department').length;
  }

  getAverageSalary(): string {
    const avg = aggregate(this.sampleData, 'salary', ['avg']);
    return '$' + Math.round(avg['avg'] || 0).toLocaleString();
  }

  getActiveCount(): number {
    const activeCount = this.sampleData.filter(emp => emp.active).length;
    return Math.round((activeCount / this.sampleData.length) * 100);
  }

  // Event handlers
  applySingleSort(): void {
    // Triggers computed update
  }

  applySearchFilter(): void {
    // Triggers computed update  
  }

  applyPropertyFilter(): void {
    // Triggers computed update
  }

  updatePagination(): void {
    // Ensure page is within bounds
    const maxPage = this.paginationResult().totalPages;
    if (this.currentPage() > maxPage) {
      this.currentPage.set(maxPage || 1);
    }
  }

  previousPage(): void {
    if (this.paginationResult().hasPrevious) {
      this.currentPage.update(page => page - 1);
    }
  }

  nextPage(): void {
    if (this.paginationResult().hasNext) {
      this.currentPage.update(page => page + 1);
    }
  }

  goToPage(page: number | string): void {
    if (typeof page === 'number') {
      this.currentPage.set(page);
    }
  }

  updateCombinedDemo(): void {
    // Triggers computed update
  }
}