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

declare global {
  interface HTMLElementTagNameMap {
    'sz-route-card': SzRouteCard;
  }
}

// Simplified route types for display purposes
export type TRouteActionType = 'forward' | 'socket-handler';
export type TTlsMode = 'passthrough' | 'terminate' | 'terminate-and-reencrypt';
export type TPortRange = number | number[] | Array<{ from: number; to: number }>;

export interface IRouteMatch {
  ports: TPortRange;
  domains?: string | string[];
  path?: string;
  clientIp?: string[];
  tlsVersion?: string[];
  headers?: Record<string, string>;
  protocol?: 'http' | 'tcp';
}

export interface IRouteTarget {
  host: string | string[];
  port: number | 'preserve';
}

export interface IRouteTls {
  mode: TTlsMode;
  certificate?: 'auto' | { key: string; cert: string };
}

export interface IRouteAction {
  type: TRouteActionType;
  targets?: IRouteTarget[];
  tls?: IRouteTls;
  websocket?: { enabled: boolean };
  loadBalancing?: { algorithm: 'round-robin' | 'least-connections' | 'ip-hash' };
  forwardingEngine?: 'node' | 'nftables';
}

export interface IRouteSecurity {
  ipAllowList?: string[];
  ipBlockList?: string[];
  maxConnections?: number;
  rateLimit?: { enabled: boolean; maxRequests: number; window: number };
}

export interface IRouteMetadata {
  sourceProfileRef?: string;
  networkTargetRef?: string;
  sourceProfileName?: string;
  networkTargetName?: string;
  lastResolvedAt?: number;
}

export interface IRouteConfig {
  id?: string;
  match: IRouteMatch;
  action: IRouteAction;
  security?: IRouteSecurity;
  headers?: { request?: Record<string, string>; response?: Record<string, string> };
  metadata?: IRouteMetadata;
  /** When true, only VPN clients whose TargetProfile matches this route get access */
  vpnOnly?: boolean;
  name?: string;
  description?: string;
  priority?: number;
  tags?: string[];
  enabled?: boolean;
}

function formatPorts(ports: TPortRange): string {
  if (typeof ports === 'number') return String(ports);
  if (Array.isArray(ports)) {
    return ports
      .map((p) => {
        if (typeof p === 'number') return String(p);
        return `${p.from}\u2013${p.to}`;
      })
      .join(', ');
  }
  return String(ports);
}

function formatTargets(targets: IRouteTarget[]): string[] {
  const result: string[] = [];
  for (const t of targets) {
    const hosts = Array.isArray(t.host) ? t.host : [t.host];
    const portStr = t.port === 'preserve' ? '(preserve)' : String(t.port);
    for (const h of hosts) {
      result.push(`${h}:${portStr}`);
    }
  }
  return result;
}

@customElement('sz-route-card')
export class SzRouteCard extends DeesElement {
  public static demo = () => html`
    <div style="padding: 24px; max-width: 520px;">
      <sz-route-card
        .route=${{
          name: 'API Gateway',
          description: 'Main API gateway with TLS termination and load balancing',
          enabled: true,
          priority: 10,
          tags: ['web', 'api', 'production'],
          match: {
            ports: [443, 8443],
            domains: ['api.example.com', '*.api.serve.zone'],
            path: '/api/*',
            protocol: 'http' as const,
            clientIp: ['10.0.0.0/8'],
          },
          action: {
            type: 'forward' as const,
            targets: [
              { host: ['10.0.0.1', '10.0.0.2'], port: 8080 },
            ],
            tls: { mode: 'terminate' as const, certificate: 'auto' as const },
            websocket: { enabled: true },
            loadBalancing: { algorithm: 'round-robin' as const },
            forwardingEngine: 'nftables' as const,
          },
          security: {
            ipAllowList: ['10.0.0.0/8'],
            ipBlockList: ['192.168.100.0/24'],
            rateLimit: { enabled: true, maxRequests: 100, window: 60 },
            maxConnections: 1000,
          },
          vpnOnly: true,
          metadata: {
            sourceProfileName: 'STANDARD',
            networkTargetName: 'LOSSLESS_INFRA',
          },
        } satisfies IRouteConfig}
      ></sz-route-card>
    </div>
  `;

  public static demoGroups = ['Routes'];

  @property({ type: Object })
  public accessor route: IRouteConfig | null = null;

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

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

      dees-tile::part(outer) {
        transition: border-color 200ms ease, box-shadow 200ms ease;
      }

      dees-tile:hover::part(outer) {
        border-color: var(--dees-color-border-strong);
        box-shadow: 0 2px 8px ${cssManager.bdTheme('rgba(0,0,0,0.06)', 'rgba(0,0,0,0.2)')};
      }

      /* Header */
      .header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        height: 40px;
        padding: 0 16px;
        width: 100%;
        box-sizing: border-box;
      }

      .header-left {
        display: flex;
        align-items: center;
        gap: 8px;
        min-width: 0;
        flex: 1;
      }

      .status-dot {
        width: 8px;
        height: 8px;
        border-radius: 50%;
        flex-shrink: 0;
      }

      .status-dot.enabled {
        background: ${cssManager.bdTheme('#22c55e', '#22c55e')};
        box-shadow: 0 0 6px ${cssManager.bdTheme('rgba(34,197,94,0.4)', 'rgba(34,197,94,0.3)')};
      }

      .status-dot.disabled {
        background: ${cssManager.bdTheme('#a1a1aa', '#52525b')};
      }

      .route-name {
        font-size: 14px;
        font-weight: 500;
        letter-spacing: -0.01em;
        color: var(--dees-color-text-secondary);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }

      .header-badges {
        display: flex;
        gap: 6px;
        flex-shrink: 0;
      }

      .badge {
        display: inline-flex;
        align-items: center;
        padding: 2px 8px;
        border-radius: 9999px;
        font-size: 11px;
        font-weight: 500;
        white-space: nowrap;
      }

      .badge.forward {
        background: ${cssManager.bdTheme('#dbeafe', 'rgba(59, 130, 246, 0.2)')};
        color: ${cssManager.bdTheme('#2563eb', '#60a5fa')};
      }

      .badge.socket-handler {
        background: ${cssManager.bdTheme('#ede9fe', 'rgba(139, 92, 246, 0.2)')};
        color: ${cssManager.bdTheme('#7c3aed', '#a78bfa')};
      }

      .badge.enabled {
        background: ${cssManager.bdTheme('#dcfce7', 'rgba(34, 197, 94, 0.2)')};
        color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
      }

      .badge.disabled {
        background: ${cssManager.bdTheme('#f4f4f5', 'rgba(113, 113, 122, 0.2)')};
        color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
      }

      .card-body {
        padding: 16px 20px;
      }

      .description {
        font-size: 13px;
        color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
        margin-bottom: 8px;
        line-height: 1.4;
      }

      .meta-row {
        display: flex;
        align-items: center;
        justify-content: space-between;
        flex-wrap: wrap;
        gap: 6px;
        margin-bottom: 16px;
      }

      .tags {
        display: flex;
        flex-wrap: wrap;
        gap: 4px;
      }

      .tag {
        padding: 2px 8px;
        background: ${cssManager.bdTheme('#f4f4f5', '#27272a')};
        border-radius: 4px;
        font-size: 11px;
        font-weight: 500;
        color: ${cssManager.bdTheme('#52525b', '#a1a1aa')};
      }

      .priority {
        font-size: 11px;
        color: ${cssManager.bdTheme('#a1a1aa', '#71717a')};
        font-weight: 500;
      }

      /* Sections */
      .section {
        border-left: 3px solid;
        padding: 10px 14px;
        margin-bottom: 12px;
        border-radius: 0 6px 6px 0;
        background: ${cssManager.bdTheme('#fafafa', '#101010')};
      }

      .section:last-of-type {
        margin-bottom: 0;
      }

      .section.match {
        border-left-color: ${cssManager.bdTheme('#3b82f6', '#3b82f6')};
      }

      .section.action {
        border-left-color: ${cssManager.bdTheme('#22c55e', '#22c55e')};
      }

      .section.security {
        border-left-color: ${cssManager.bdTheme('#f59e0b', '#f59e0b')};
      }

      .section.linked {
        border-left-color: ${cssManager.bdTheme('#8b5cf6', '#8b5cf6')};
      }

      .linked-name {
        display: inline-flex;
        padding: 1px 6px;
        border-radius: 3px;
        font-size: 12px;
        font-weight: 600;
        font-family: monospace;
        background: ${cssManager.bdTheme('#ede9fe', 'rgba(139, 92, 246, 0.15)')};
        color: ${cssManager.bdTheme('#6d28d9', '#a78bfa')};
      }

      .section-label {
        font-size: 10px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.08em;
        color: ${cssManager.bdTheme('#a1a1aa', '#71717a')};
        margin-bottom: 8px;
      }

      .field-row {
        display: flex;
        gap: 8px;
        margin-bottom: 5px;
        font-size: 13px;
        line-height: 1.5;
      }

      .field-row:last-child {
        margin-bottom: 0;
      }

      .field-key {
        color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
        min-width: 64px;
        flex-shrink: 0;
        font-weight: 500;
      }

      .field-value {
        color: ${cssManager.bdTheme('#18181b', '#e4e4e7')};
        word-break: break-all;
      }

      .domain-chip {
        display: inline-flex;
        padding: 1px 6px;
        background: ${cssManager.bdTheme('#eff6ff', 'rgba(59, 130, 246, 0.1)')};
        border-radius: 3px;
        font-size: 12px;
        margin-right: 4px;
        margin-bottom: 2px;
        font-family: monospace;
      }

      .domain-chip.glob {
        background: ${cssManager.bdTheme('#fef3c7', 'rgba(245, 158, 11, 0.15)')};
        color: ${cssManager.bdTheme('#92400e', '#fbbf24')};
      }

      .mono {
        font-family: monospace;
        font-size: 12px;
      }

      .protocol-badge {
        display: inline-flex;
        padding: 1px 6px;
        border-radius: 3px;
        font-size: 11px;
        font-weight: 500;
      }

      .protocol-badge.http {
        background: ${cssManager.bdTheme('#dbeafe', 'rgba(59, 130, 246, 0.2)')};
        color: ${cssManager.bdTheme('#2563eb', '#60a5fa')};
      }

      .protocol-badge.tcp {
        background: ${cssManager.bdTheme('#dcfce7', 'rgba(34, 197, 94, 0.2)')};
        color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
      }

      .tls-badge {
        display: inline-flex;
        padding: 1px 6px;
        border-radius: 3px;
        font-size: 11px;
        font-weight: 500;
      }

      .tls-badge.auto {
        background: ${cssManager.bdTheme('#dcfce7', 'rgba(34, 197, 94, 0.2)')};
        color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
      }

      .tls-badge.custom {
        background: ${cssManager.bdTheme('#ffedd5', 'rgba(249, 115, 22, 0.2)')};
        color: ${cssManager.bdTheme('#c2410c', '#fb923c')};
      }

      .engine-badge {
        display: inline-flex;
        padding: 1px 6px;
        border-radius: 3px;
        font-size: 11px;
        font-weight: 500;
        background: ${cssManager.bdTheme('#fae8ff', 'rgba(168, 85, 247, 0.2)')};
        color: ${cssManager.bdTheme('#7e22ce', '#c084fc')};
      }

      .header-pair {
        display: inline;
        font-family: monospace;
        font-size: 12px;
      }

      /* Feature icons */
      .features-row {
        display: flex;
        flex-wrap: wrap;
        gap: 10px;
        margin-top: 14px;
        padding-top: 12px;
        border-top: 1px solid ${cssManager.bdTheme('#f4f4f5', '#1a1a1a')};
      }

      .feature {
        display: flex;
        align-items: center;
        gap: 4px;
        font-size: 11px;
        font-weight: 500;
        color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
      }

      .feature-icon {
        font-size: 13px;
      }

      .no-route {
        text-align: center;
        padding: 24px;
        color: ${cssManager.bdTheme('#a1a1aa', '#52525b')};
        font-size: 13px;
      }

      .section.vpn {
        border-left-color: ${cssManager.bdTheme('#0891b2', '#06b6d4')};
      }

      .vpn-badge {
        display: inline-flex;
        align-items: center;
        padding: 2px 8px;
        border-radius: 9999px;
        font-size: 11px;
        font-weight: 600;
        white-space: nowrap;
      }

      .vpn-badge.mandatory {
        background: ${cssManager.bdTheme('#fff7ed', 'rgba(249, 115, 22, 0.2)')};
        color: ${cssManager.bdTheme('#c2410c', '#fb923c')};
      }

      .vpn-badge.optional {
        background: ${cssManager.bdTheme('#ecfdf5', 'rgba(16, 185, 129, 0.2)')};
        color: ${cssManager.bdTheme('#047857', '#34d399')};
      }

      .vpn-tag {
        display: inline-flex;
        padding: 1px 6px;
        border-radius: 3px;
        font-size: 12px;
        font-weight: 600;
        font-family: monospace;
        margin-right: 4px;
        margin-bottom: 2px;
        background: ${cssManager.bdTheme('#ecfeff', 'rgba(6, 182, 212, 0.15)')};
        color: ${cssManager.bdTheme('#0e7490', '#22d3ee')};
      }

      .card-footer {
        display: flex;
        flex-direction: row;
        justify-content: flex-end;
        align-items: center;
        gap: 0;
        height: 36px;
        width: 100%;
        box-sizing: border-box;
      }

      .tile-button {
        padding: 0 16px;
        height: 100%;
        text-align: center;
        font-size: 12px;
        font-weight: 500;
        cursor: pointer;
        user-select: none;
        transition: all 0.15s ease;
        background: transparent;
        border: none;
        border-left: 1px solid var(--dees-color-border-subtle);
        color: var(--dees-color-text-muted);
        white-space: nowrap;
        display: flex;
        align-items: center;
        gap: 6px;
        font-family: inherit;
      }

      .tile-button:first-child {
        border-left: none;
      }

      .tile-button:hover {
        background: var(--dees-color-hover);
        color: var(--dees-color-text-primary);
      }

      .tile-button.edit:hover {
        color: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8%)', 'hsl(213.1 93.9% 67.8%)')};
      }

      .tile-button.delete:hover {
        background: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.1)')};
        color: ${cssManager.bdTheme('#dc2626', '#f87171')};
      }
    `,
  ];

  public render(): TemplateResult {
    if (!this.route) {
      return html`
        <dees-tile>
          <div class="card-body"><div class="no-route">No route data</div></div>
        </dees-tile>
      `;
    }

    const r = this.route;
    const isEnabled = r.enabled !== false;
    const match = r.match;
    const action = r.action;
    const security = r.security;

    return html`
      <dees-tile>
        <!-- Header -->
        <div slot="header" class="header">
          <div class="header-left">
            <span class="status-dot ${isEnabled ? 'enabled' : 'disabled'}"></span>
            <span class="route-name">${r.name || r.id || 'Unnamed Route'}</span>
          </div>
          <div class="header-badges">
            <span class="badge ${action.type}">${action.type}</span>
            <span class="badge ${isEnabled ? 'enabled' : 'disabled'}">${isEnabled ? 'enabled' : 'disabled'}</span>
          </div>
        </div>

        <div class="card-body">
          ${r.description ? html`<div class="description">${r.description}</div>` : ''}

          <div class="meta-row">
            ${r.tags && r.tags.length > 0
              ? html`<div class="tags">${r.tags.map((t) => html`<span class="tag">${t}</span>`)}</div>`
              : html`<div></div>`}
            ${r.priority != null ? html`<span class="priority">Priority: ${r.priority}</span>` : ''}
          </div>

          <!-- Match Section -->
        <div class="section match">
          <div class="section-label">Match</div>
          <div class="field-row">
            <span class="field-key">Ports</span>
            <span class="field-value mono">${formatPorts(match.ports)}</span>
          </div>
          ${match.domains
            ? html`
                <div class="field-row">
                  <span class="field-key">Domains</span>
                  <span class="field-value">${this.renderDomains(match.domains)}</span>
                </div>
              `
            : ''}
          ${match.path
            ? html`
                <div class="field-row">
                  <span class="field-key">Path</span>
                  <span class="field-value mono">${match.path}</span>
                </div>
              `
            : ''}
          ${match.protocol
            ? html`
                <div class="field-row">
                  <span class="field-key">Protocol</span>
                  <span class="field-value">
                    <span class="protocol-badge ${match.protocol}">${match.protocol}</span>
                  </span>
                </div>
              `
            : ''}
          ${match.clientIp && match.clientIp.length > 0
            ? html`
                <div class="field-row">
                  <span class="field-key">Client</span>
                  <span class="field-value mono">${match.clientIp.join(', ')}</span>
                </div>
              `
            : ''}
          ${match.tlsVersion && match.tlsVersion.length > 0
            ? html`
                <div class="field-row">
                  <span class="field-key">TLS Ver</span>
                  <span class="field-value">${match.tlsVersion.join(', ')}</span>
                </div>
              `
            : ''}
          ${match.headers
            ? html`
                <div class="field-row">
                  <span class="field-key">Headers</span>
                  <span class="field-value">
                    ${Object.entries(match.headers).map(
                      ([k, v]) => html`<span class="header-pair">${k}=${v}</span> `
                    )}
                  </span>
                </div>
              `
            : ''}
        </div>

        <!-- Action Section -->
        <div class="section action">
          <div class="section-label">Action</div>
          ${action.targets && action.targets.length > 0
            ? html`
                <div class="field-row">
                  <span class="field-key">Targets</span>
                  <span class="field-value mono">${formatTargets(action.targets).join(', ')}</span>
                </div>
              `
            : ''}
          ${action.tls
            ? html`
                <div class="field-row">
                  <span class="field-key">TLS</span>
                  <span class="field-value">
                    ${action.tls.mode}
                    ${action.tls.certificate
                      ? action.tls.certificate === 'auto'
                        ? html` <span class="tls-badge auto">auto cert</span>`
                        : html` <span class="tls-badge custom">custom cert</span>`
                      : ''}
                  </span>
                </div>
              `
            : ''}
          ${action.forwardingEngine
            ? html`
                <div class="field-row">
                  <span class="field-key">Engine</span>
                  <span class="field-value"><span class="engine-badge">${action.forwardingEngine}</span></span>
                </div>
              `
            : ''}
          ${action.loadBalancing
            ? html`
                <div class="field-row">
                  <span class="field-key">LB</span>
                  <span class="field-value">${action.loadBalancing.algorithm}</span>
                </div>
              `
            : ''}
          ${action.websocket?.enabled
            ? html`
                <div class="field-row">
                  <span class="field-key">WS</span>
                  <span class="field-value"><span class="badge enabled">enabled</span></span>
                </div>
              `
            : ''}
        </div>

        <!-- Security Section -->
        ${security
          ? html`
              <div class="section security">
                <div class="section-label">Security</div>
                ${security.ipAllowList && security.ipAllowList.length > 0
                  ? html`
                      <div class="field-row">
                        <span class="field-key">Allow</span>
                        <span class="field-value mono">${security.ipAllowList.join(', ')}</span>
                      </div>
                    `
                  : ''}
                ${security.ipBlockList && security.ipBlockList.length > 0
                  ? html`
                      <div class="field-row">
                        <span class="field-key">Block</span>
                        <span class="field-value mono">${security.ipBlockList.join(', ')}</span>
                      </div>
                    `
                  : ''}
                ${security.rateLimit?.enabled
                  ? html`
                      <div class="field-row">
                        <span class="field-key">Rate</span>
                        <span class="field-value">${security.rateLimit.maxRequests} req / ${security.rateLimit.window}s</span>
                      </div>
                    `
                  : ''}
                ${security.maxConnections
                  ? html`
                      <div class="field-row">
                        <span class="field-key">Max Conn</span>
                        <span class="field-value">${security.maxConnections}</span>
                      </div>
                    `
                  : ''}
              </div>
            `
          : ''}

          <!-- VPN Section -->
          ${this.renderVpn()}

          <!-- Linked References Section -->
          ${this.renderLinked()}

          <!-- Feature Icons Row -->
          ${this.renderFeatures()}
        </div>

        <!-- Action Buttons -->
        ${this.showActions ? html`
          <div slot="footer" class="card-footer">
            <button class="tile-button edit" @click=${(e: Event) => {
              e.stopPropagation();
              this.dispatchEvent(new CustomEvent('route-edit', {
                detail: this.route,
                bubbles: true,
                composed: true,
              }));
            }}>Edit</button>
            <button class="tile-button delete" @click=${(e: Event) => {
              e.stopPropagation();
              this.dispatchEvent(new CustomEvent('route-delete', {
                detail: this.route,
                bubbles: true,
                composed: true,
              }));
            }}>Delete</button>
          </div>
        ` : ''}
      </dees-tile>
    `;
  }

  private renderDomains(domains: string | string[]): TemplateResult {
    const list = Array.isArray(domains) ? domains : [domains];
    return html`${list.map(
      (d) =>
        html`<span class="domain-chip ${d.includes('*') ? 'glob' : ''}">${d}</span>`
    )}`;
  }

  private renderVpn(): TemplateResult {
    if (!this.route?.vpnOnly) return html``;

    return html`
      <div class="section vpn">
        <div class="section-label">VPN Access</div>
        <div class="field-row">
          <span class="field-key">Mode</span>
          <span class="field-value">
            <span class="vpn-badge mandatory">VPN Only</span>
          </span>
        </div>
      </div>
    `;
  }

  private renderLinked(): TemplateResult {
    const meta = this.route?.metadata;
    if (!meta) return html``;
    const hasProfile = !!meta.sourceProfileName;
    const hasTarget = !!meta.networkTargetName;
    if (!hasProfile && !hasTarget) return html``;

    return html`
      <div class="section linked">
        <div class="section-label">Linked</div>
        ${hasProfile
          ? html`
              <div class="field-row">
                <span class="field-key">Profile</span>
                <span class="field-value"><span class="linked-name">${meta.sourceProfileName}</span></span>
              </div>
            `
          : ''}
        ${hasTarget
          ? html`
              <div class="field-row">
                <span class="field-key">Target</span>
                <span class="field-value"><span class="linked-name">${meta.networkTargetName}</span></span>
              </div>
            `
          : ''}
      </div>
    `;
  }

  private renderFeatures(): TemplateResult {
    if (!this.route) return html``;
    const features: TemplateResult[] = [];
    const action = this.route.action;
    const security = this.route.security;
    const headers = this.route.headers;
    const meta = this.route.metadata;

    if (action.tls) {
      features.push(html`<span class="feature"><span class="feature-icon">&#x1f512;</span>TLS</span>`);
    }
    if (action.websocket?.enabled) {
      features.push(html`<span class="feature"><span class="feature-icon">&#x2194;</span>WS</span>`);
    }
    if (action.loadBalancing) {
      features.push(html`<span class="feature"><span class="feature-icon">&#x2696;</span>LB</span>`);
    }
    if (security) {
      features.push(html`<span class="feature"><span class="feature-icon">&#x1f6e1;</span>Security</span>`);
    }
    if (headers) {
      features.push(html`<span class="feature"><span class="feature-icon">&#x2699;</span>Headers</span>`);
    }
    if (this.route?.vpnOnly) {
      features.push(html`<span class="feature"><span class="feature-icon">&#x1f510;</span>VPN</span>`);
    }
    if (meta?.sourceProfileName || meta?.networkTargetName) {
      features.push(html`<span class="feature"><span class="feature-icon">&#x1f517;</span>Linked</span>`);
    }

    if (features.length === 0) return html``;
    return html`<div class="features-row">${features}</div>`;
  }
}
