import { LitElement, html, css, property, state, customElement } from './plugins.js';
import type { CSSResult, TemplateResult } from './plugins.js';
import { sharedStyles, tableStyles } from './sw-dash-styles.js';

export interface IColumnConfig {
  key: string;
  label: string;
  sortable?: boolean;
  formatter?: (value: any, row: any) => string;
  className?: string;
}

/**
 * Base sortable table component for sw-dash
 */
@customElement('sw-dash-table')
export class SwDashTable extends LitElement {
  public static styles: CSSResult[] = [
    sharedStyles,
    tableStyles,
    css`
      :host {
        display: block;
      }
    `
  ];

  @property({ type: Array }) accessor columns: IColumnConfig[] = [];
  @property({ type: Array }) accessor data: any[] = [];
  @property({ type: String }) accessor filterPlaceholder = 'Filter...';
  @property({ type: String }) accessor infoLabel = 'items';

  @state() accessor sortColumn = '';
  @state() accessor sortDirection: 'asc' | 'desc' = 'desc';
  @state() accessor filterText = '';

  // Utility formatters
  static formatNumber(n: number): string {
    return n.toLocaleString();
  }

  static formatBytes(bytes: number): string {
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  }

  static formatTimestamp(ts: number): string {
    if (!ts || ts === 0) return 'never';
    const ago = Date.now() - ts;
    if (ago < 60000) return Math.floor(ago / 1000) + 's ago';
    if (ago < 3600000) return Math.floor(ago / 60000) + 'm ago';
    if (ago < 86400000) return Math.floor(ago / 3600000) + 'h ago';
    return new Date(ts).toLocaleDateString();
  }

  static getGaugeClass(rate: number): string {
    if (rate >= 80) return 'good';
    if (rate >= 50) return 'warning';
    return 'bad';
  }

  private handleSort(column: string): void {
    if (this.sortColumn === column) {
      this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
    } else {
      this.sortColumn = column;
      this.sortDirection = 'desc';
    }
  }

  private handleFilter(e: Event): void {
    this.filterText = (e.target as HTMLInputElement).value;
  }

  private getSortedFilteredData(): any[] {
    let result = [...this.data];

    // Filter
    if (this.filterText) {
      const search = this.filterText.toLowerCase();
      result = result.filter(row => {
        return this.columns.some(col => {
          const val = row[col.key];
          if (val == null) return false;
          return String(val).toLowerCase().includes(search);
        });
      });
    }

    // Sort
    if (this.sortColumn) {
      result.sort((a, b) => {
        let valA = a[this.sortColumn];
        let valB = b[this.sortColumn];
        if (typeof valA === 'string') valA = valA.toLowerCase();
        if (typeof valB === 'string') valB = valB.toLowerCase();
        if (valA < valB) return this.sortDirection === 'asc' ? -1 : 1;
        if (valA > valB) return this.sortDirection === 'asc' ? 1 : -1;
        return 0;
      });
    }

    return result;
  }

  private renderHitRateBar(rate: number): TemplateResult {
    const cls = SwDashTable.getGaugeClass(rate);
    return html`
      <span class="hit-rate-bar">
        <span class="hit-rate-fill ${cls}" style="width: ${rate}%"></span>
      </span>${rate}%
    `;
  }

  protected renderCellValue(value: any, row: any, column: IColumnConfig): any {
    if (column.formatter) {
      return column.formatter(value, row);
    }
    // Special handling for hitRate
    if (column.key === 'hitRate') {
      return this.renderHitRateBar(value);
    }
    return value;
  }

  public render(): TemplateResult {
    const sortedData = this.getSortedFilteredData();

    return html`
      <div class="table-controls">
        <input
          type="text"
          class="search-input"
          placeholder="${this.filterPlaceholder}"
          .value="${this.filterText}"
          @input="${this.handleFilter}"
        >
        <span class="table-info">${sortedData.length} of ${this.data.length} ${this.infoLabel}</span>
      </div>
      <div class="table-container">
        <table class="data-table">
          <thead>
            <tr>
              ${this.columns.map(col => html`
                <th
                  class="${this.sortColumn === col.key ? 'sorted' : ''}"
                  @click="${() => col.sortable !== false && this.handleSort(col.key)}"
                >
                  ${col.label}
                  ${col.sortable !== false ? html`
                    <span class="sort-icon">${this.sortColumn === col.key && this.sortDirection === 'asc' ? '↑' : '↓'}</span>
                  ` : ''}
                </th>
              `)}
            </tr>
          </thead>
          <tbody>
            ${sortedData.map(row => html`
              <tr>
                ${this.columns.map(col => html`
                  <td class="${col.className || ''}">${this.renderCellValue(row[col.key], row, col)}</td>
                `)}
              </tr>
            `)}
          </tbody>
        </table>
      </div>
    `;
  }
}
