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

import type { IRouteConfig, TRouteActionType } from './sz-route-card.js';

declare global {
  interface HTMLElementTagNameMap {
    'sz-route-list-view': SzRouteListView;
  }
}

@customElement('sz-route-list-view')
export class SzRouteListView extends DeesElement {
  public static demo = () => html`
    <div style="padding: 24px; max-width: 1200px;">
      <sz-route-list-view
        .routes=${[
          {
            name: 'HTTPS Gateway',
            description: 'Main web gateway with TLS termination',
            enabled: true,
            tags: ['web', 'https', 'production'],
            match: { ports: 443, domains: ['*.example.com', 'serve.zone'], protocol: 'http' as const },
            action: {
              type: 'forward' as const,
              targets: [{ host: '10.0.0.1', port: 8080 }],
              tls: { mode: 'terminate' as const, certificate: 'auto' as const },
            },
          },
          {
            name: 'SMTP Inbound',
            description: 'Email relay for incoming mail',
            enabled: true,
            tags: ['email', 'smtp'],
            match: { ports: 25, domains: 'mail.serve.zone' },
            action: {
              type: 'forward' as const,
              targets: [{ host: '10.0.1.5', port: 25 }],
            },
          },
          {
            name: 'WebSocket API',
            description: 'Real-time WebSocket connections',
            enabled: true,
            tags: ['web', 'api'],
            match: { ports: 443, domains: 'ws.example.com', path: '/ws/*' },
            action: {
              type: 'forward' as const,
              targets: [{ host: '10.0.0.3', port: 9090 }],
              websocket: { enabled: true },
              tls: { mode: 'terminate' as const, certificate: 'auto' as const },
            },
          },
          {
            name: 'Maintenance Page',
            enabled: false,
            tags: ['web'],
            match: { ports: [80, 443], domains: 'old.example.com' },
            action: { type: 'socket-handler' as const },
          },
        ] satisfies IRouteConfig[]}
      ></sz-route-list-view>
    </div>
  `;

  public static demoGroups = ['Routes'];

  @property({ type: Array })
  public accessor routes: IRouteConfig[] = [];

  @property({ attribute: false })
  public accessor showActionsFilter: ((route: IRouteConfig) => boolean) | null = null;

  @state()
  private accessor searchQuery: string = '';

  @state()
  private accessor actionFilter: TRouteActionType | 'all' = 'all';

  @state()
  private accessor enabledFilter: 'all' | 'enabled' | 'disabled' = 'all';

  private get filteredRoutes(): IRouteConfig[] {
    return this.routes.filter((route) => {
      // Action type filter
      if (this.actionFilter !== 'all' && route.action.type !== this.actionFilter) return false;

      // Enabled/disabled filter
      if (this.enabledFilter === 'enabled' && route.enabled === false) return false;
      if (this.enabledFilter === 'disabled' && route.enabled !== false) return false;

      // Search query
      if (this.searchQuery) {
        const q = this.searchQuery.toLowerCase();
        return this.routeMatchesSearch(route, q);
      }
      return true;
    });
  }

  private routeMatchesSearch(route: IRouteConfig, q: string): boolean {
    // Name and description
    if (route.name?.toLowerCase().includes(q)) return true;
    if (route.description?.toLowerCase().includes(q)) return true;

    // Domains
    if (route.match.domains) {
      const domains = Array.isArray(route.match.domains) ? route.match.domains : [route.match.domains];
      if (domains.some((d) => d.toLowerCase().includes(q))) return true;
    }

    // Ports
    const portsStr = this.formatPortsForSearch(route.match.ports);
    if (portsStr.includes(q)) return true;

    // Path
    if (route.match.path?.toLowerCase().includes(q)) return true;

    // Client IPs
    if (route.match.clientIp?.some((ip) => ip.includes(q))) return true;

    // Targets
    if (route.action.targets) {
      for (const t of route.action.targets) {
        const hosts = Array.isArray(t.host) ? t.host : [t.host];
        if (hosts.some((h) => h.toLowerCase().includes(q))) return true;
      }
    }

    // Tags
    if (route.tags?.some((t) => t.toLowerCase().includes(q))) return true;

    return false;
  }

  private formatPortsForSearch(ports: import('./sz-route-card.js').TPortRange): string {
    if (typeof ports === 'number') return String(ports);
    if (Array.isArray(ports)) {
      return ports
        .map((p) => (typeof p === 'number' ? String(p) : `${p.from}-${p.to}`))
        .join(' ');
    }
    return String(ports);
  }

  public static styles = [
    cssManager.defaultStyles,
    css`
      :host {
        display: block;
      }

      .filter-bar {
        display: flex;
        flex-wrap: wrap;
        gap: 12px;
        align-items: center;
        margin-bottom: 12px;
      }

      .search-input {
        flex: 1;
        min-width: 200px;
        padding: 8px 12px;
        background: ${cssManager.bdTheme('#ffffff', '#09090b')};
        border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
        border-radius: 6px;
        font-size: 14px;
        color: ${cssManager.bdTheme('#18181b', '#fafafa')};
        outline: none;
        transition: border-color 200ms ease;
      }

      .search-input::placeholder {
        color: ${cssManager.bdTheme('#a1a1aa', '#52525b')};
      }

      .search-input:focus {
        border-color: ${cssManager.bdTheme('#2563eb', '#3b82f6')};
      }

      .chip-group {
        display: flex;
        gap: 4px;
      }

      .chip {
        padding: 6px 12px;
        background: transparent;
        border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
        border-radius: 9999px;
        font-size: 12px;
        font-weight: 500;
        color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
        cursor: pointer;
        transition: all 200ms ease;
        white-space: nowrap;
      }

      .chip:hover {
        background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
        color: ${cssManager.bdTheme('#18181b', '#fafafa')};
      }

      .chip.active {
        background: ${cssManager.bdTheme('#18181b', '#fafafa')};
        color: ${cssManager.bdTheme('#fafafa', '#18181b')};
        border-color: ${cssManager.bdTheme('#18181b', '#fafafa')};
      }

      .results-count {
        font-size: 13px;
        color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
        margin-bottom: 16px;
      }

      .grid {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
        gap: 16px;
      }

      .grid sz-route-card {
        cursor: pointer;
      }

      .empty-state {
        text-align: center;
        padding: 48px 24px;
        color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
        font-size: 14px;
      }

      .empty-state-icon {
        font-size: 32px;
        margin-bottom: 12px;
        opacity: 0.5;
      }
    `,
  ];

  public render(): TemplateResult {
    const filtered = this.filteredRoutes;

    return html`
      <div class="filter-bar">
        <input
          class="search-input"
          type="text"
          placeholder="Search routes by domain, IP, port, path, or tag..."
          .value=${this.searchQuery}
          @input=${(e: InputEvent) => {
            this.searchQuery = (e.target as HTMLInputElement).value;
          }}
        />
        <div class="chip-group">
          ${(['all', 'forward', 'socket-handler'] as const).map(
            (type) => html`
              <button
                class="chip ${this.actionFilter === type ? 'active' : ''}"
                @click=${() => {
                  this.actionFilter = type;
                }}
              >
                ${type === 'all' ? 'All' : type === 'forward' ? 'Forward' : 'Socket Handler'}
              </button>
            `
          )}
        </div>
        <div class="chip-group">
          ${(['all', 'enabled', 'disabled'] as const).map(
            (status) => html`
              <button
                class="chip ${this.enabledFilter === status ? 'active' : ''}"
                @click=${() => {
                  this.enabledFilter = status;
                }}
              >
                ${status.charAt(0).toUpperCase() + status.slice(1)}
              </button>
            `
          )}
        </div>
      </div>

      <div class="results-count">
        Showing ${filtered.length} of ${this.routes.length} routes
      </div>

      ${filtered.length > 0
        ? html`
            <div class="grid">
              ${filtered.map(
                (route) => html`
                  <sz-route-card
                    .route=${route}
                    .showActions=${this.showActionsFilter?.(route) ?? false}
                    @click=${() => this.handleRouteClick(route)}
                  ></sz-route-card>
                `
              )}
            </div>
          `
        : html`
            <div class="empty-state">
              <div class="empty-state-icon">&#x1f50d;</div>
              <div>No routes match your filters</div>
            </div>
          `}
    `;
  }

  private handleRouteClick(route: IRouteConfig) {
    this.dispatchEvent(
      new CustomEvent('route-click', {
        detail: route,
        bubbles: true,
        composed: true,
      })
    );
  }
}
