import * as plugins from '../plugins.js';
import * as shared from './shared/index.js';
import * as appstate from '../appstate.js';

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

@customElement('ops-view-overview')
export class OpsViewOverview extends DeesElement {
  @state()
  accessor statsState: appstate.IStatsState = {
    serverStats: null,
    emailStats: null,
    dnsStats: null,
    securityMetrics: null,
    lastUpdated: 0,
    isLoading: false,
    error: null,
  };

  @state()
  accessor logState: appstate.ILogState = {
    recentLogs: [],
    isStreaming: false,
    filters: {},
  };

  constructor() {
    super();
    const statsSub = appstate.statsStatePart
      .select((stateArg) => stateArg)
      .subscribe((statsState) => {
        this.statsState = statsState;
      });
    this.rxSubscriptions.push(statsSub);

    const logSub = appstate.logStatePart
      .select((stateArg) => stateArg)
      .subscribe((logState) => {
        this.logState = logState;
      });
    this.rxSubscriptions.push(logSub);
  }

  async connectedCallback() {
    super.connectedCallback();
    // Ensure logs are fetched for the overview charts
    if (this.logState.recentLogs.length === 0) {
      appstate.logStatePart.dispatchAction(appstate.fetchRecentLogsAction, { limit: 100 });
    }
  }

  public static styles = [
    cssManager.defaultStyles,
    shared.viewHostCss,
    css`
      h2 {
        margin: 32px 0 16px 0;
        font-size: 24px;
        font-weight: 600;
        color: ${cssManager.bdTheme('#333', '#ccc')};
      }

      .chartGrid {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        grid-gap: 16px;
        margin-top: 32px;
      }

      .loadingMessage {
        text-align: center;
        padding: 40px;
        color: ${cssManager.bdTheme('#666', '#999')};
      }

      .errorMessage {
        background-color: ${cssManager.bdTheme('#fee', '#4a1f1f')};
        border: 1px solid ${cssManager.bdTheme('#fcc', '#6a2f2f')};
        border-radius: 4px;
        padding: 16px;
        color: ${cssManager.bdTheme('#c00', '#ff6666')};
        margin: 16px 0;
      }

      dees-statsgrid {
        margin-bottom: 32px;
      }
    `,
  ];

  public render() {
    return html`
      <ops-sectionheading>Overview</ops-sectionheading>
      
      ${this.statsState.isLoading ? html`
        <div class="loadingMessage">
          <dees-spinner></dees-spinner>
          <p>Loading statistics...</p>
        </div>
      ` : this.statsState.error ? html`
        <div class="errorMessage">
          Error loading statistics: ${this.statsState.error}
        </div>
      ` : html`
        ${this.renderServerStats()}

        ${this.renderEmailStats()}

        ${this.renderDnsStats()}

        <div class="chartGrid">
          <dees-chart-area
            .label=${'Email Traffic (24h)'}
            .series=${this.getEmailTrafficSeries()}
            .realtimeMode=${true}
            .rollingWindow=${86400000}
            .yAxisFormatter=${(val: number) => `${val}`}
          ></dees-chart-area>
          <dees-chart-area
            .label=${'DNS Queries (24h)'}
            .series=${this.getDnsQuerySeries()}
            .realtimeMode=${true}
            .rollingWindow=${86400000}
            .yAxisFormatter=${(val: number) => `${val}`}
          ></dees-chart-area>
          <dees-chart-log
            .label=${'Recent Events'}
            .logEntries=${this.getRecentEventEntries()}
          ></dees-chart-log>
          <dees-chart-log
            .label=${'DNS Queries'}
            .logEntries=${this.getDnsQueryEntries()}
          ></dees-chart-log>
        </div>
      `}
    `;
  }

  private formatUptime(seconds: number): string {
    const days = Math.floor(seconds / 86400);
    const hours = Math.floor((seconds % 86400) / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const secs = Math.floor(seconds % 60);
    
    if (days > 0) {
      return `${days}d ${hours}h ${minutes}m ${secs}s`;
    } else if (hours > 0) {
      return `${hours}h ${minutes}m ${secs}s`;
    } else if (minutes > 0) {
      return `${minutes}m ${secs}s`;
    } else {
      return `${secs}s`;
    }
  }

  private formatBytes(bytes: number): string {
    const units = ['B', 'KB', 'MB', 'GB', 'TB'];
    let size = bytes;
    let unitIndex = 0;

    while (size >= 1024 && unitIndex < units.length - 1) {
      size /= 1024;
      unitIndex++;
    }

    return `${size.toFixed(1)} ${units[unitIndex]}`;
  }

  private formatBitsPerSecond(bytesPerSecond: number): string {
    const bitsPerSecond = bytesPerSecond * 8;
    const units = ['bit/s', 'kbit/s', 'Mbit/s', 'Gbit/s'];
    let size = bitsPerSecond;
    let unitIndex = 0;

    while (size >= 1000 && unitIndex < units.length - 1) {
      size /= 1000;
      unitIndex++;
    }

    return `${size.toFixed(1)} ${units[unitIndex]}`;
  }

  private renderServerStats(): TemplateResult {
    if (!this.statsState.serverStats) return html``;

    const cpuUsage = Math.round(this.statsState.serverStats.cpuUsage.user);
    const memoryUsage = this.statsState.serverStats.memoryUsage.actualUsagePercentage !== undefined
      ? Math.round(this.statsState.serverStats.memoryUsage.actualUsagePercentage)
      : Math.round((this.statsState.serverStats.memoryUsage.heapUsed / this.statsState.serverStats.memoryUsage.heapTotal) * 100);

    const tiles: IStatsTile[] = [
      {
        id: 'status',
        title: 'Server Status',
        value: this.statsState.serverStats.uptime ? 'Online' : 'Offline',
        type: 'text',
        icon: 'lucide:Server',
        color: this.statsState.serverStats.uptime ? '#22c55e' : '#ef4444',
        description: `Uptime: ${this.formatUptime(this.statsState.serverStats.uptime)}`,
      },
      {
        id: 'connections',
        title: 'Active Connections',
        value: this.statsState.serverStats.activeConnections,
        type: 'number',
        icon: 'lucide:Network',
        color: '#3b82f6',
        description: `Total: ${this.statsState.serverStats.totalConnections}`,
      },
      {
        id: 'throughputIn',
        title: 'Throughput In',
        value: this.formatBitsPerSecond(this.statsState.serverStats.throughput?.bytesInPerSecond || 0),
        type: 'text',
        icon: 'lucide:Download',
        color: '#22c55e',
        description: `Total: ${this.formatBytes(this.statsState.serverStats.throughput?.bytesIn || 0)}`,
      },
      {
        id: 'throughputOut',
        title: 'Throughput Out',
        value: this.formatBitsPerSecond(this.statsState.serverStats.throughput?.bytesOutPerSecond || 0),
        type: 'text',
        icon: 'lucide:Upload',
        color: '#8b5cf6',
        description: `Total: ${this.formatBytes(this.statsState.serverStats.throughput?.bytesOut || 0)}`,
      },
      {
        id: 'cpu',
        title: 'CPU Usage',
        value: cpuUsage,
        type: 'gauge',
        icon: 'lucide:Cpu',
        gaugeOptions: {
          min: 0,
          max: 100,
          thresholds: [
            { value: 0, color: '#22c55e' },
            { value: 60, color: '#f59e0b' },
            { value: 80, color: '#ef4444' },
          ],
        },
      },
      {
        id: 'memory',
        title: 'Memory Usage',
        value: memoryUsage,
        type: 'percentage',
        icon: 'lucide:MemoryStick',
        color: memoryUsage > 80 ? '#ef4444' : memoryUsage > 60 ? '#f59e0b' : '#22c55e',
        description: this.statsState.serverStats.memoryUsage.actualUsageBytes !== undefined && this.statsState.serverStats.memoryUsage.maxMemoryMB !== undefined
          ? `${this.formatBytes(this.statsState.serverStats.memoryUsage.actualUsageBytes)} / ${this.formatBytes(this.statsState.serverStats.memoryUsage.maxMemoryMB * 1024 * 1024)}`
          : `${this.formatBytes(this.statsState.serverStats.memoryUsage.rss)} / ${this.formatBytes(this.statsState.serverStats.memoryUsage.heapTotal)}`,
      },
    ];

    return html`
      <dees-statsgrid
        .tiles=${tiles}
        .gridActions=${[
          {
            name: 'Refresh',
            iconName: 'lucide:RefreshCw',
            action: async () => {
              await appstate.statsStatePart.dispatchAction(appstate.fetchAllStatsAction, null);
            },
          },
        ]}
      ></dees-statsgrid>
    `;
  }

  private renderEmailStats(): TemplateResult {
    if (!this.statsState.emailStats) return html``;

    const deliveryRate = this.statsState.emailStats.deliveryRate || 0;
    const bounceRate = this.statsState.emailStats.bounceRate || 0;

    const tiles: IStatsTile[] = [
      {
        id: 'sent',
        title: 'Emails Sent',
        value: this.statsState.emailStats.sent,
        type: 'number',
        icon: 'lucide:Send',
        color: '#22c55e',
        description: `Delivery rate: ${(deliveryRate * 100).toFixed(1)}%`,
      },
      {
        id: 'received',
        title: 'Emails Received',
        value: this.statsState.emailStats.received,
        type: 'number',
        icon: 'lucide:Mail',
        color: '#3b82f6',
      },
      {
        id: 'queued',
        title: 'Queued',
        value: this.statsState.emailStats.queued,
        type: 'number',
        icon: 'lucide:Clock',
        color: '#f59e0b',
        description: 'Pending delivery',
      },
      {
        id: 'failed',
        title: 'Failed',
        value: this.statsState.emailStats.failed,
        type: 'number',
        icon: 'lucide:TriangleAlert',
        color: '#ef4444',
        description: `Bounce rate: ${(bounceRate * 100).toFixed(1)}%`,
      },
    ];

    return html`
      <h2>Email Statistics</h2>
      <dees-statsgrid .tiles=${tiles}></dees-statsgrid>
    `;
  }

  private renderDnsStats(): TemplateResult {
    if (!this.statsState.dnsStats) return html``;

    const cacheHitRate = Math.round(this.statsState.dnsStats.cacheHitRate * 100);

    const tiles: IStatsTile[] = [
      {
        id: 'queries',
        title: 'DNS Queries',
        value: this.statsState.dnsStats.totalQueries,
        type: 'number',
        icon: 'lucide:Globe',
        color: '#3b82f6',
        description: 'Total queries handled',
      },
      {
        id: 'cacheRate',
        title: 'Cache Hit Rate',
        value: cacheHitRate,
        type: 'percentage',
        icon: 'lucide:Database',
        color: cacheHitRate > 80 ? '#22c55e' : cacheHitRate > 60 ? '#f59e0b' : '#ef4444',
        description: `${this.statsState.dnsStats.cacheHits} hits / ${this.statsState.dnsStats.cacheMisses} misses`,
      },
      {
        id: 'domains',
        title: 'Active Domains',
        value: this.statsState.dnsStats.activeDomains,
        type: 'number',
        icon: 'lucide:Network',
        color: '#8b5cf6',
      },
      {
        id: 'responseTime',
        title: 'Avg Response Time',
        value: this.statsState.dnsStats.averageResponseTime.toFixed(1),
        unit: 'ms',
        type: 'number',
        icon: 'lucide:History',
        color: this.statsState.dnsStats.averageResponseTime < 50 ? '#22c55e' : '#f59e0b',
      },
    ];

    return html`
      <h2>DNS Statistics</h2>
      <dees-statsgrid .tiles=${tiles}></dees-statsgrid>
    `;
  }

  // --- Chart data helpers ---

  private getRecentEventEntries(): Array<{ timestamp: string; level: 'debug' | 'info' | 'warn' | 'error' | 'success'; message: string; source?: string }> {
    return this.logState.recentLogs.map((log) => ({
      timestamp: new Date(log.timestamp).toISOString(),
      level: log.level as 'debug' | 'info' | 'warn' | 'error',
      message: log.message,
      source: log.category,
    }));
  }

  private getSecurityAlertEntries(): Array<{ timestamp: string; level: 'debug' | 'info' | 'warn' | 'error' | 'success'; message: string; source?: string }> {
    const events: any[] = this.statsState.securityMetrics?.recentEvents || [];
    return events.map((evt: any) => ({
      timestamp: new Date(evt.timestamp).toISOString(),
      level: evt.level === 'critical' || evt.level === 'error' ? 'error' as const : evt.level === 'warn' ? 'warn' as const : 'info' as const,
      message: evt.message,
      source: evt.type,
    }));
  }

  private getDnsQueryEntries(): Array<{ timestamp: string; level: 'debug' | 'info' | 'warn' | 'error' | 'success'; message: string; source?: string }> {
    const queries: any[] = (this.statsState.dnsStats as any)?.recentQueries || [];
    return queries.map((q: any) => ({
      timestamp: new Date(q.timestamp).toISOString(),
      level: q.answered ? 'info' as const : 'warn' as const,
      message: `${q.type} ${q.domain} (${q.responseTimeMs}ms)`,
      source: 'dns',
    }));
  }

  private getEmailTrafficSeries(): Array<{ name: string; color: string; data: Array<{ x: number; y: number }> }> {
    const ts = this.statsState.emailStats?.timeSeries;
    if (!ts) return [];
    return [
      { name: 'Sent', color: '#22c55e', data: (ts.sent || []).map((p: any) => ({ x: p.timestamp, y: p.value })) },
      { name: 'Received', color: '#3b82f6', data: (ts.received || []).map((p: any) => ({ x: p.timestamp, y: p.value })) },
    ];
  }

  private getDnsQuerySeries(): Array<{ name: string; color: string; data: Array<{ x: number; y: number }> }> {
    const ts = this.statsState.dnsStats?.timeSeries;
    if (!ts) return [];
    return [
      { name: 'Queries', color: '#8b5cf6', data: (ts.queries || []).map((p: any) => ({ x: p.timestamp, y: p.value })) },
    ];
  }
}