import { DeesElement, customElement, html, css, cssManager, state, type TemplateResult } from '../plugins.js';
import { deesCatalog } from '../plugins.js';
import { type IStatsTile } from '@design.estate/dees-catalog';
import { appState, type IAppState, type ICallStatus, type ICallHistoryEntry, type ILegStatus, type IDeviceStatus } from '../state/appstate.js';
import { viewHostCss } from './shared/index.js';

const STATE_LABELS: Record<string, string> = {
  'setting-up': 'Setting Up',
  'ringing': 'Ringing',
  'connected': 'Connected',
  'on-hold': 'On Hold',
  'transferring': 'Transferring',
  'terminating': 'Hanging Up',
  'terminated': 'Ended',
};

function stateBadgeStyle(s: string): string {
  if (s.includes('ringing') || s === 'setting-up') return 'background:#854d0e;color:#fbbf24';
  if (s === 'connected') return 'background:#166534;color:#4ade80';
  if (s === 'on-hold') return 'background:#1e3a5f;color:#38bdf8';
  return 'background:#7f1d1d;color:#f87171';
}

function legTypeBadgeStyle(type: string): string {
  if (type === 'sip-device') return 'background:#1e3a5f;color:#38bdf8';
  if (type === 'sip-provider') return 'background:#4a1d7a;color:#c084fc';
  if (type === 'webrtc') return 'background:#065f46;color:#34d399';
  return 'background:#374151;color:#9ca3af';
}

const LEG_TYPE_LABELS: Record<string, string> = {
  'sip-device': 'SIP Device',
  'sip-provider': 'SIP Provider',
  'webrtc': 'WebRTC',
  'tool': 'Tool',
};

function renderHistoryLegs(legs: ICallHistoryEntry['legs']): TemplateResult {
  if (!legs.length) {
    return html`<span style="color:#64748b">-</span>`;
  }

  return html`
    <div style="display:flex;flex-direction:column;gap:6px;font-size:.72rem;line-height:1.35;">
      ${legs.map(
        (leg) => html`
          <div>
            <span class="badge" style="${legTypeBadgeStyle(leg.type)}">${LEG_TYPE_LABELS[leg.type] || leg.type}</span>
            <span style="margin-left:6px;font-family:'JetBrains Mono',monospace;">${leg.codec || '--'}</span>
            <span style="margin-left:6px;color:#94a3b8;">${STATE_LABELS[leg.state] || leg.state}</span>
            ${leg.remoteMedia
              ? html`<span style="display:block;color:#64748b;font-family:'JetBrains Mono',monospace;">${leg.remoteMedia}</span>`
              : ''}
          </div>
        `,
      )}
    </div>
  `;
}

function directionIcon(dir: string): string {
  if (dir === 'inbound') return '\u2199';
  if (dir === 'outbound') return '\u2197';
  return '\u2194';
}

function fmtDuration(sec: number): string {
  const m = Math.floor(sec / 60);
  const s = sec % 60;
  if (m > 0) return `${m}m ${String(s).padStart(2, '0')}s`;
  return `${s}s`;
}

function fmtTime(ts: number): string {
  const d = new Date(ts);
  return d.toLocaleString(undefined, {
    month: 'short', day: 'numeric',
    hour: '2-digit', minute: '2-digit', second: '2-digit',
  });
}

@customElement('sipproxy-view-calls')
export class SipproxyViewCalls extends DeesElement {
  @state() accessor appData: IAppState = appState.getState();

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

      .view-section {
        margin-bottom: 24px;
      }

      .calls-list {
        display: flex;
        flex-direction: column;
        gap: 16px;
      }

      /* Active call tile content */
      .call-header {
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 12px 16px;
        flex-wrap: wrap;
      }

      .direction-icon {
        font-size: 1.1rem;
        width: 28px;
        height: 28px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 6px;
        background: var(--dees-color-bg-primary, #0f172a);
        border: 1px solid var(--dees-color-border-default, #334155);
        flex-shrink: 0;
      }

      .call-parties {
        flex: 1;
        min-width: 0;
        font-size: 0.85rem;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }

      .call-parties .label {
        color: var(--dees-color-text-secondary, #64748b);
        font-size: 0.7rem;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        margin-right: 4px;
      }

      .call-meta {
        display: flex;
        align-items: center;
        gap: 8px;
        flex-shrink: 0;
      }

      .badge {
        display: inline-block;
        font-size: 0.6rem;
        padding: 2px 7px;
        border-radius: 3px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.02em;
        white-space: nowrap;
      }

      .call-duration {
        font-size: 0.8rem;
        color: var(--dees-color-text-secondary, #94a3b8);
        font-family: 'JetBrains Mono', monospace;
        white-space: nowrap;
      }

      .call-id {
        font-family: 'JetBrains Mono', monospace;
        font-size: 0.65rem;
        color: #475569;
        padding: 0 16px 8px;
      }

      .call-body {
        padding: 12px 16px 16px;
        display: grid;
        gap: 16px;
      }

      .call-overview {
        display: grid;
        grid-template-columns: minmax(0, 1.6fr) minmax(240px, 0.9fr);
        gap: 14px;
      }

      .call-route-card,
      .call-facts-card,
      .legs-section {
        border-radius: 14px;
        border: 1px solid rgba(51, 65, 85, 0.75);
        background:
          linear-gradient(180deg, rgba(15, 23, 42, 0.92) 0%, rgba(8, 15, 31, 0.88) 100%);
        box-shadow: inset 0 1px 0 rgba(148, 163, 184, 0.08);
      }

      .call-route-card,
      .call-facts-card {
        padding: 14px;
      }

      .section-kicker {
        font-size: 0.62rem;
        font-weight: 700;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: #64748b;
      }

      .route-line {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
        align-items: center;
        gap: 12px;
        margin-top: 12px;
      }

      .route-party {
        min-width: 0;
        display: flex;
        flex-direction: column;
        gap: 4px;
        padding: 12px;
        border-radius: 12px;
        background: rgba(15, 23, 42, 0.6);
        border: 1px solid rgba(71, 85, 105, 0.45);
      }

      .route-party.align-end {
        text-align: right;
        align-items: flex-end;
      }

      .route-party-label {
        font-size: 0.64rem;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: #64748b;
      }

      .route-party-value {
        min-width: 0;
        font-size: 0.95rem;
        font-weight: 600;
        color: #e2e8f0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }

      .route-arrow {
        width: 34px;
        height: 34px;
        border-radius: 999px;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 1rem;
        color: #93c5fd;
        background: rgba(30, 41, 59, 0.8);
        border: 1px solid rgba(59, 130, 246, 0.35);
      }

      .call-tags {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        margin-top: 12px;
      }

      .subtle-badge {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        padding: 5px 9px;
        border-radius: 999px;
        font-size: 0.66rem;
        font-weight: 700;
        letter-spacing: 0.03em;
        color: #cbd5e1;
        background: rgba(30, 41, 59, 0.9);
        border: 1px solid rgba(71, 85, 105, 0.45);
      }

      .call-facts-card {
        display: grid;
        gap: 8px;
      }

      .fact-row {
        display: flex;
        justify-content: space-between;
        align-items: flex-start;
        gap: 12px;
        padding: 7px 0;
        border-bottom: 1px solid rgba(51, 65, 85, 0.55);
      }

      .fact-row:last-child {
        border-bottom: none;
        padding-bottom: 0;
      }

      .fact-label {
        font-size: 0.65rem;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: #64748b;
      }

      .fact-value {
        font-family: 'JetBrains Mono', monospace;
        font-size: 0.76rem;
        text-align: right;
        color: #e2e8f0;
        word-break: break-word;
      }

      .legs-section {
        padding: 14px;
        display: grid;
        gap: 12px;
      }

      .legs-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 12px;
      }

      .legs-grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
        gap: 12px;
      }

      .leg-card {
        display: grid;
        gap: 12px;
        padding: 12px;
        border-radius: 12px;
        background: rgba(15, 23, 42, 0.6);
        border: 1px solid rgba(71, 85, 105, 0.4);
      }

      .leg-card-top {
        display: flex;
        justify-content: space-between;
        align-items: flex-start;
        gap: 10px;
      }

      .leg-card-badges {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
      }

      .leg-card-id {
        font-family: 'JetBrains Mono', monospace;
        font-size: 0.64rem;
        color: #64748b;
        word-break: break-all;
        text-align: right;
      }

      .leg-facts {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 10px 12px;
      }

      .leg-fact {
        display: flex;
        flex-direction: column;
        gap: 4px;
        min-width: 0;
      }

      .leg-fact-wide {
        grid-column: 1 / -1;
      }

      .leg-fact-label {
        font-size: 0.62rem;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: #64748b;
      }

      .leg-fact-value {
        font-family: 'JetBrains Mono', monospace;
        font-size: 0.76rem;
        color: #e2e8f0;
        word-break: break-word;
      }

      .leg-actions {
        display: flex;
        justify-content: flex-end;
      }

      .no-legs {
        padding: 16px;
        border-radius: 12px;
        border: 1px dashed rgba(71, 85, 105, 0.55);
        color: #64748b;
        font-size: 0.75rem;
        text-align: center;
      }

      .card-actions {
        display: flex;
        gap: 8px;
        flex-wrap: wrap;
        padding-top: 4px;
      }

      .btn {
        padding: 6px 14px;
        border: none;
        border-radius: 6px;
        font-size: 0.7rem;
        font-weight: 600;
        cursor: pointer;
        transition: opacity 0.15s;
        white-space: nowrap;
      }

      .btn:hover { opacity: 0.85; }
      .btn:active { opacity: 0.7; }
      .btn-danger { background: #dc2626; color: #fff; }
      .btn-primary { background: #2563eb; color: #fff; }
      .btn-secondary { background: #334155; color: #e2e8f0; }

      .btn-remove {
        background: transparent;
        color: #f87171;
        border: 1px solid #7f1d1d;
        padding: 3px 10px;
        font-size: 0.65rem;
      }

      .empty-state {
        text-align: center;
        padding: 48px 16px;
        color: #64748b;
      }
      .empty-state-icon { font-size: 2.5rem; margin-bottom: 12px; opacity: 0.4; }
      .empty-state-text { font-size: 0.9rem; font-weight: 500; }
      .empty-state-sub { font-size: 0.75rem; margin-top: 4px; }

      @media (max-width: 820px) {
        .call-overview {
          grid-template-columns: 1fr;
        }

        .route-line {
          grid-template-columns: 1fr;
        }

        .route-arrow {
          justify-self: center;
          transform: rotate(90deg);
        }

        .route-party.align-end {
          text-align: left;
          align-items: flex-start;
        }

        .leg-card-top {
          flex-direction: column;
        }

        .leg-card-id {
          text-align: left;
        }
      }
    `,
  ];

  async connectedCallback(): Promise<void> {
    await super.connectedCallback();
    this.rxSubscriptions.push({
      unsubscribe: appState.subscribe((s) => {
        this.appData = s;
      }),
    } as any);
  }

  private async handleAddParticipant(call: ICallStatus) {
    const devices = this.appData.devices?.filter((d) => d.connected) || [];
    let selectedDeviceId = devices.length > 0 ? devices[0].id : '';

    await deesCatalog.DeesModal.createAndShow({
      heading: 'Add Participant',
      width: 'small',
      showCloseButton: true,
      content: html`
        <div style="padding: 0.5rem 0;">
          <div style="font-size:.7rem;color:#64748b;margin-bottom:.35rem;text-transform:uppercase;letter-spacing:.04em;">
            Select Device
          </div>
          <select
            style="width:100%;padding:.5rem .6rem;border-radius:6px;border:1px solid #334155;background:#0c0f1a;color:#e2e8f0;font-size:.85rem;outline:none;box-sizing:border-box;"
            @change=${(e: Event) => {
              selectedDeviceId = (e.target as HTMLSelectElement).value;
            }}
          >
            ${devices.map(
              (d) => html`<option value=${d.id}>${d.displayName}${d.isBrowser ? ' (Browser)' : ''}</option>`,
            )}
          </select>
          ${devices.length === 0
            ? html`<div style="color:#f87171;font-size:.75rem;margin-top:.5rem;">No connected devices available.</div>`
            : ''}
        </div>
      `,
      menuOptions: [
        {
          name: 'Add',
          iconName: 'lucide:plus',
          action: async (modalRef: any) => {
            if (!selectedDeviceId) return;
            const res = await appState.apiAddLeg(call.id, selectedDeviceId);
            if (res.ok) {
              deesCatalog.DeesToast.success('Participant added');
            } else {
              deesCatalog.DeesToast.error('Failed to add participant');
            }
            modalRef.destroy();
          },
        },
        {
          name: 'Cancel',
          iconName: 'lucide:x',
          action: async (modalRef: any) => {
            modalRef.destroy();
          },
        },
      ],
    });
  }

  private async handleAddExternal(call: ICallStatus) {
    const providers = this.appData.providers?.filter((p) => p.registered) || [];
    let number = '';
    let selectedProviderId = providers.length > 0 ? providers[0].id : '';

    await deesCatalog.DeesModal.createAndShow({
      heading: 'Add External Participant',
      width: 'small',
      showCloseButton: true,
      content: html`
        <div style="padding: 0.5rem 0;">
          <div style="font-size:.7rem;color:#64748b;margin-bottom:.35rem;text-transform:uppercase;letter-spacing:.04em;">
            Phone Number
          </div>
          <input
            type="tel"
            placeholder="Enter number to dial..."
            style="width:100%;padding:.5rem .6rem;border-radius:6px;border:1px solid #334155;background:#0c0f1a;color:#e2e8f0;font-size:.95rem;font-family:'JetBrains Mono',monospace;outline:none;box-sizing:border-box;margin-bottom:12px;"
            @input=${(e: InputEvent) => { number = (e.target as HTMLInputElement).value; }}
          >
          <div style="font-size:.7rem;color:#64748b;margin-bottom:.35rem;text-transform:uppercase;letter-spacing:.04em;">
            Via Provider
          </div>
          <select
            style="width:100%;padding:.5rem .6rem;border-radius:6px;border:1px solid #334155;background:#0c0f1a;color:#e2e8f0;font-size:.85rem;outline:none;box-sizing:border-box;"
            @change=${(e: Event) => { selectedProviderId = (e.target as HTMLSelectElement).value; }}
          >
            ${providers.map(
              (p) => html`<option value=${p.id}>${p.displayName}</option>`,
            )}
          </select>
          ${providers.length === 0
            ? html`<div style="color:#f87171;font-size:.75rem;margin-top:.5rem;">No registered providers available.</div>`
            : ''}
        </div>
      `,
      menuOptions: [
        {
          name: 'Dial',
          iconName: 'lucide:phoneOutgoing',
          action: async (modalRef: any) => {
            if (!number.trim()) {
              deesCatalog.DeesToast.error('Enter a phone number');
              return;
            }
            const res = await appState.apiAddExternal(call.id, number.trim(), selectedProviderId || undefined);
            if (res.ok) {
              deesCatalog.DeesToast.success(`Dialing ${number}...`);
            } else {
              deesCatalog.DeesToast.error('Failed to dial external number');
            }
            modalRef.destroy();
          },
        },
        {
          name: 'Cancel',
          iconName: 'lucide:x',
          action: async (modalRef: any) => {
            modalRef.destroy();
          },
        },
      ],
    });
  }

  private async handleRemoveLeg(call: ICallStatus, leg: ILegStatus) {
    const res = await appState.apiRemoveLeg(call.id, leg.id);
    if (res.ok) {
      deesCatalog.DeesToast.success('Leg removed');
    } else {
      deesCatalog.DeesToast.error('Failed to remove leg');
    }
  }

  private async handleTransfer(call: ICallStatus) {
    let targetCallId = '';
    let targetLegId = '';

    const otherCalls =
      this.appData.calls?.filter((c) => c.id !== call.id && c.state !== 'terminated') || [];

    await deesCatalog.DeesModal.createAndShow({
      heading: 'Transfer Call',
      width: 'small',
      showCloseButton: true,
      content: html`
        <div style="padding: 0.5rem 0;">
          <div style="margin-bottom: 1rem;">
            <div style="font-size:.7rem;color:#64748b;margin-bottom:.35rem;text-transform:uppercase;letter-spacing:.04em;">
              Target Call ID
            </div>
            <select
              style="width:100%;padding:.5rem .6rem;border-radius:6px;border:1px solid #334155;background:#0c0f1a;color:#e2e8f0;font-size:.85rem;outline:none;box-sizing:border-box;"
              @change=${(e: Event) => {
                targetCallId = (e.target as HTMLSelectElement).value;
              }}
            >
              <option value="">Select a call...</option>
              ${otherCalls.map(
                (c) =>
                  html`<option value=${c.id}>
                    ${c.direction} - ${c.callerNumber || '?'} -> ${c.calleeNumber || '?'}
                  </option>`,
              )}
            </select>
          </div>
          <div>
            <div style="font-size:.7rem;color:#64748b;margin-bottom:.35rem;text-transform:uppercase;letter-spacing:.04em;">
              Leg ID to transfer
            </div>
            <select
              style="width:100%;padding:.5rem .6rem;border-radius:6px;border:1px solid #334155;background:#0c0f1a;color:#e2e8f0;font-size:.85rem;outline:none;box-sizing:border-box;"
              @change=${(e: Event) => {
                targetLegId = (e.target as HTMLSelectElement).value;
              }}
            >
              <option value="">Select a leg...</option>
              ${call.legs.map(
                (l) =>
                  html`<option value=${l.id}>${LEG_TYPE_LABELS[l.type] || l.type} - ${l.state}</option>`,
              )}
            </select>
          </div>
          ${otherCalls.length === 0
            ? html`<div style="color:#f87171;font-size:.75rem;margin-top:.75rem;">
                No other active calls to transfer to.
              </div>`
            : ''}
        </div>
      `,
      menuOptions: [
        {
          name: 'Transfer',
          iconName: 'lucide:ArrowRightLeft',
          action: async (modalRef: any) => {
            if (!targetCallId || !targetLegId) {
              deesCatalog.DeesToast.error('Please select both a target call and a leg');
              return;
            }
            const res = await appState.apiTransfer(call.id, targetLegId, targetCallId);
            if (res.ok) {
              deesCatalog.DeesToast.success('Transfer initiated');
            } else {
              deesCatalog.DeesToast.error('Transfer failed');
            }
            modalRef.destroy();
          },
        },
        {
          name: 'Cancel',
          iconName: 'lucide:x',
          action: async (modalRef: any) => {
            modalRef.destroy();
          },
        },
      ],
    });
  }

  private async handleHangup(call: ICallStatus) {
    await appState.apiHangup(call.id);
  }

  private getHistoryColumns() {
    return [
      {
        key: 'direction',
        header: 'Direction',
        renderer: (val: string) => {
          return html`<span style="margin-right:6px">${directionIcon(val)}</span><span class="badge" style="background:#374151;color:#9ca3af">${val}</span>`;
        },
      },
      {
        key: 'callerNumber',
        header: 'From',
        renderer: (val: string | null) =>
          html`<span style="font-family:'JetBrains Mono',monospace;font-size:.8rem">${val || '-'}</span>`,
      },
      {
        key: 'calleeNumber',
        header: 'To',
        renderer: (val: string | null) =>
          html`<span style="font-family:'JetBrains Mono',monospace;font-size:.8rem">${val || '-'}</span>`,
      },
      {
        key: 'providerUsed',
        header: 'Provider',
        renderer: (val: string | null) => val || '-',
      },
      {
        key: 'startedAt',
        header: 'Time',
        renderer: (val: number) =>
          html`<span style="font-family:'JetBrains Mono',monospace;font-size:.75rem">${fmtTime(val)}</span>`,
      },
      {
        key: 'duration',
        header: 'Duration',
        renderer: (val: number) =>
          html`<span style="font-family:'JetBrains Mono',monospace;font-size:.75rem">${fmtDuration(val)}</span>`,
      },
      {
        key: 'legs',
        header: 'Legs',
        renderer: (val: ICallHistoryEntry['legs']) => renderHistoryLegs(val),
      },
    ];
  }

  private renderCallCard(call: ICallStatus): TemplateResult {
    return html`
      <dees-tile>
        <div slot="header">
          <div class="call-header">
            <div class="direction-icon">${directionIcon(call.direction)}</div>
            <div class="call-parties">
              ${call.callerNumber
                ? html`<span class="label">From</span>${call.callerNumber}`
                : ''}
              ${call.callerNumber && call.calleeNumber ? html` &rarr; ` : ''}
              ${call.calleeNumber
                ? html`<span class="label">To</span>${call.calleeNumber}`
                : ''}
            </div>
            <div class="call-meta">
              <span class="badge" style="${stateBadgeStyle(call.state)}">
                ${STATE_LABELS[call.state] || call.state}
              </span>
              ${call.providerUsed
                ? html`<span class="badge" style="background:#374151;color:#9ca3af">${call.providerUsed}</span>`
                : ''}
              <span class="call-duration">${fmtDuration(call.duration)}</span>
            </div>
          </div>
        </div>
        <div class="call-id">${call.id}</div>
        <div class="call-body">
          <div class="call-overview">
            <div class="call-route-card">
              <div class="section-kicker">Call Route</div>
              <div class="route-line">
                <div class="route-party">
                  <div class="route-party-label">From</div>
                  <div class="route-party-value">${call.callerNumber || 'Unknown caller'}</div>
                </div>
                <div class="route-arrow">${directionIcon(call.direction)}</div>
                <div class="route-party align-end">
                  <div class="route-party-label">To</div>
                  <div class="route-party-value">${call.calleeNumber || 'System'}</div>
                </div>
              </div>
              <div class="call-tags">
                <span class="subtle-badge">${call.legs.length} ${call.legs.length === 1 ? 'leg' : 'legs'}</span>
                <span class="subtle-badge">${call.providerUsed || 'system handled'}</span>
                <span class="subtle-badge">started ${fmtTime(call.startedAt)}</span>
              </div>
            </div>

            <div class="call-facts-card">
              <div class="section-kicker">Session</div>
              <div class="fact-row">
                <span class="fact-label">State</span>
                <span class="fact-value">${STATE_LABELS[call.state] || call.state}</span>
              </div>
              <div class="fact-row">
                <span class="fact-label">Direction</span>
                <span class="fact-value">${call.direction}</span>
              </div>
              <div class="fact-row">
                <span class="fact-label">Duration</span>
                <span class="fact-value">${fmtDuration(call.duration)}</span>
              </div>
              <div class="fact-row">
                <span class="fact-label">Provider</span>
                <span class="fact-value">${call.providerUsed || '--'}</span>
              </div>
            </div>
          </div>

          <div class="legs-section">
            <div class="legs-header">
              <div class="section-kicker">Active Legs</div>
              <span class="subtle-badge">${call.legs.length}</span>
            </div>

            ${call.legs.length
              ? html`
                  <div class="legs-grid">
                    ${call.legs.map(
                      (leg) => html`
                        <div class="leg-card">
                          <div class="leg-card-top">
                            <div class="leg-card-badges">
                              <span class="badge" style="${legTypeBadgeStyle(leg.type)}">
                                ${LEG_TYPE_LABELS[leg.type] || leg.type}
                              </span>
                              <span class="badge" style="${stateBadgeStyle(leg.state)}">
                                ${STATE_LABELS[leg.state] || leg.state}
                              </span>
                            </div>
                            <div class="leg-card-id">${leg.id}</div>
                          </div>

                          <div class="leg-facts">
                            <div class="leg-fact">
                              <span class="leg-fact-label">Codec</span>
                              <span class="leg-fact-value">${leg.codec || '--'}${leg.transcoding ? ' (transcode)' : ''}</span>
                            </div>
                            <div class="leg-fact">
                              <span class="leg-fact-label">RTP Port</span>
                              <span class="leg-fact-value">${leg.rtpPort ?? '--'}</span>
                            </div>
                            <div class="leg-fact leg-fact-wide">
                              <span class="leg-fact-label">Remote Media</span>
                              <span class="leg-fact-value">${leg.remoteMedia || '--'}</span>
                            </div>
                            <div class="leg-fact">
                              <span class="leg-fact-label">Packets In</span>
                              <span class="leg-fact-value">${leg.pktReceived}</span>
                            </div>
                            <div class="leg-fact">
                              <span class="leg-fact-label">Packets Out</span>
                              <span class="leg-fact-value">${leg.pktSent}</span>
                            </div>
                          </div>

                          <div class="leg-actions">
                            <button
                              class="btn btn-remove"
                              @click=${() => this.handleRemoveLeg(call, leg)}
                            >
                              Remove
                            </button>
                          </div>
                        </div>
                      `,
                    )}
                  </div>
                `
              : html`<div class="no-legs">No legs reported yet. SIP/system legs should appear here as soon as the call is wired.</div>`}
          </div>

          <div class="card-actions">
            <button class="btn btn-primary" @click=${() => this.handleAddParticipant(call)}>
              Add Device
            </button>
            <button class="btn btn-primary" @click=${() => this.handleAddExternal(call)}>
              Add External
            </button>
            <button class="btn btn-secondary" @click=${() => this.handleTransfer(call)}>
              Transfer
            </button>
            <button class="btn btn-danger" @click=${() => this.handleHangup(call)}>
              Hang Up
            </button>
          </div>
        </div>
      </dees-tile>
    `;
  }

  public render(): TemplateResult {
    const { appData } = this;
    const activeCalls = appData.calls?.filter((c) => c.state !== 'terminated') || [];
    const history = appData.callHistory || [];
    const inboundCount = activeCalls.filter((c) => c.direction === 'inbound').length;
    const outboundCount = activeCalls.filter((c) => c.direction === 'outbound').length;

    const tiles: IStatsTile[] = [
      {
        id: 'active',
        title: 'Active Calls',
        value: activeCalls.length,
        type: 'number',
        icon: 'lucide:phone',
        color: 'hsl(142.1 76.2% 36.3%)',
        description: activeCalls.length === 1 ? '1 call' : `${activeCalls.length} calls`,
      },
      {
        id: 'inbound',
        title: 'Inbound',
        value: inboundCount,
        type: 'number',
        icon: 'lucide:PhoneIncoming',
        description: 'Incoming calls',
      },
      {
        id: 'outbound',
        title: 'Outbound',
        value: outboundCount,
        type: 'number',
        icon: 'lucide:PhoneOutgoing',
        description: 'Outgoing calls',
      },
    ];

    return html`
      <dees-heading level="3">Calls</dees-heading>

      <div class="view-section">
        <dees-statsgrid .tiles=${tiles} .minTileWidth=${220} .gap=${16}></dees-statsgrid>
      </div>

      <div class="view-section">
        <div class="calls-list">
          ${activeCalls.length > 0
            ? activeCalls.map((call) => this.renderCallCard(call))
            : html`
                <div class="empty-state">
                  <div class="empty-state-icon">&#128222;</div>
                  <div class="empty-state-text">No active calls</div>
                  <div class="empty-state-sub">
                    Calls will appear here when they are in progress
                  </div>
                </div>
              `}
        </div>
      </div>

      <div class="view-section">
        <dees-table
          heading1="Call History"
          heading2="${history.length} calls"
          dataName="calls"
          .data=${history}
          .rowKey=${'id'}
          .searchable=${true}
          .columns=${this.getHistoryColumns()}
        ></dees-table>
      </div>
    `;
  }
}
