import * as plugins from '../plugins.js';
import * as shared from './shared/index.js';
import * as appstate from '../appstate.js';
import { appRouter } from '../router.js';
import {
  DeesElement,
  customElement,
  html,
  state,
  css,
  cssManager,
  type TemplateResult,
} from '@design.estate/dees-element';

const byteUnits = ['B', 'KB', 'MB', 'GB', 'TB'];

function getByteUnitIndex(bytes: number): number {
  if (!bytes || bytes === 0) return 0;
  return Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), byteUnits.length - 1);
}

function formatBytes(bytes: number, forcedUnitIndex?: number): string {
  if ((!bytes || bytes === 0) && forcedUnitIndex === undefined) return '0 B';
  const unitIndex = forcedUnitIndex ?? getByteUnitIndex(bytes);
  const value = bytes / Math.pow(1024, unitIndex);
  return `${value.toFixed(1)} ${byteUnits[unitIndex]}`;
}

@customElement('ob-view-dashboard')
export class ObViewDashboard extends DeesElement {
  @state()
  accessor systemState: appstate.ISystemState = { status: null };

  @state()
  accessor servicesState: appstate.IServicesState = {
    services: [],
    currentService: null,
    currentServiceLogs: [],
    currentServiceStats: null,
    platformServices: [],
    currentPlatformService: null,
    currentPlatformServiceStats: null,
    currentPlatformServiceLogs: [],
  };

  @state()
  accessor networkState: appstate.INetworkState = {
    targets: [],
    stats: null,
    trafficStats: null,
    dnsRecords: [],
    domains: [],
    gatewayDomains: [],
    gatewayDnsRecords: [],
    certificates: [],
  };

  constructor() {
    super();

    const systemSub = appstate.systemStatePart
      .select((s) => s)
      .subscribe((newState) => {
        this.systemState = newState;
      });
    this.rxSubscriptions.push(systemSub);

    const servicesSub = appstate.servicesStatePart
      .select((s) => s)
      .subscribe((newState) => {
        this.servicesState = newState;
      });
    this.rxSubscriptions.push(servicesSub);

    const networkSub = appstate.networkStatePart
      .select((s) => s)
      .subscribe((newState) => {
        this.networkState = newState;
      });
    this.rxSubscriptions.push(networkSub);
  }

  public static styles = [
    cssManager.defaultStyles,
    shared.viewHostCss,
    css`
      .dashboard {
        display: flex;
        flex-direction: column;
        gap: 24px;
      }

      .section {
        display: flex;
        flex-direction: column;
      }

      .section-title {
        font-size: 18px;
        font-weight: 600;
        color: ${cssManager.bdTheme('#18181b', '#fafafa')};
        margin: 0 0 12px;
      }

      .services-grid {
        display: grid;
        grid-template-columns: 1fr;
        gap: 16px;
        align-items: stretch;
      }

      .services-grid > * {
        height: 100%;
      }

      @media (min-width: 768px) {
        .services-grid {
          grid-template-columns: 1fr 1fr;
        }
      }
    `,
  ];

  async connectedCallback() {
    super.connectedCallback();
    await Promise.all([
      appstate.systemStatePart.dispatchAction(appstate.fetchSystemStatusAction, null),
      appstate.servicesStatePart.dispatchAction(appstate.fetchServicesAction, null),
      appstate.servicesStatePart.dispatchAction(appstate.fetchPlatformServicesAction, null),
      appstate.networkStatePart.dispatchAction(appstate.fetchNetworkStatsAction, null),
      appstate.networkStatePart.dispatchAction(appstate.fetchTrafficStatsAction, null),
      appstate.networkStatePart.dispatchAction(appstate.fetchCertificatesAction, null),
    ]);
  }

  public render(): TemplateResult {
    const status = this.systemState.status;
    const services = this.servicesState.services;
    const platformServices = this.servicesState.platformServices;
    const networkStats = this.networkState.stats;
    const trafficStats = this.networkState.trafficStats;
    const certificates = this.networkState.certificates;
    const statusCounts = trafficStats?.statusCounts || {};

    const runningServices = services.filter((s) => s.status === 'running').length;
    const stoppedServices = services.filter((s) => s.status === 'stopped').length;
    const memoryUnitIndex = getByteUnitIndex(
      status?.docker?.memoryTotal || status?.docker?.memoryUsage || 0,
    );

    const validCerts = certificates.filter((c) => c.isValid).length;
    const expiringCerts = certificates.filter(
      (c) => c.isValid && c.expiresAt && c.expiresAt - Date.now() < 30 * 24 * 60 * 60 * 1000,
    ).length;
    const expiredCerts = certificates.filter((c) => !c.isValid).length;

    const dashboardData = {
      cluster: {
        totalServices: services.length,
        running: runningServices,
        stopped: stoppedServices,
        dockerStatus: status?.docker?.running ? 'running' as const : 'stopped' as const,
      },
      resourceUsage: {
        cpu: status?.docker?.cpuUsage || 0,
        memoryUsed: formatBytes(status?.docker?.memoryUsage || 0, memoryUnitIndex),
        memoryTotal: formatBytes(status?.docker?.memoryTotal || 0, memoryUnitIndex),
        networkIn: formatBytes(status?.docker?.networkIn || 0),
        networkOut: formatBytes(status?.docker?.networkOut || 0),
        topConsumers: [],
      },
      platformServices: platformServices
        .filter((ps) => ps.status === 'running' || ps.status === 'starting' || ps.status === 'stopping' || ps.isCore)
        .map((ps) => ({
          name: ps.displayName,
          status: ps.status === 'running' ? 'Running' : ps.status === 'starting' ? 'Starting...' : ps.status === 'stopping' ? 'Stopping...' : 'Stopped',
          running: ps.status === 'running',
        })),
      traffic: {
        requests: trafficStats?.requestCount || 0,
        errors: trafficStats?.errorCount || 0,
        errorPercent: trafficStats?.errorRate || 0,
        avgResponse: trafficStats?.avgResponseTime || 0,
        reqPerMin: trafficStats?.requestsPerMinute || 0,
        status2xx: statusCounts['2xx'] || 0,
        status3xx: statusCounts['3xx'] || 0,
        status4xx: statusCounts['4xx'] || 0,
        status5xx: statusCounts['5xx'] || 0,
      },
      proxy: {
        httpPort: String(networkStats?.proxy?.httpPort || 80),
        httpsPort: String(networkStats?.proxy?.httpsPort || 443),
        httpActive: networkStats?.proxy?.running || false,
        httpsActive: networkStats?.proxy?.running || false,
        routeCount: String(networkStats?.proxy?.routes || 0),
      },
      certificates: {
        valid: validCerts,
        expiring: expiringCerts,
        expired: expiredCerts,
      },
      dnsConfigured: status?.dns?.configured || false,
      acmeConfigured: status?.ssl?.configured || false,
      quickActions: [
        { label: 'Deploy Service', icon: 'lucide:Plus', primary: true },
        { label: 'Add Domain', icon: 'lucide:Globe' },
        { label: 'View Logs', icon: 'lucide:FileText' },
      ],
    };

    return html`
      <ob-sectionheading>Dashboard</ob-sectionheading>
      <div class="dashboard">
        <section class="section">
          <h2 class="section-title">Cluster Overview</h2>
          <sz-status-grid-cluster .stats=${dashboardData.cluster}></sz-status-grid-cluster>
        </section>

        <section class="section">
          <h2 class="section-title">Services & Resources</h2>
          <div class="services-grid">
            <sz-resource-usage-card .data=${dashboardData.resourceUsage}></sz-resource-usage-card>
            <sz-platform-services-card
              .services=${dashboardData.platformServices}
              @service-click=${(e: CustomEvent) => this.handlePlatformServiceClick(e)}
            ></sz-platform-services-card>
          </div>
        </section>

        <section class="section">
          <h2 class="section-title">Network & Traffic</h2>
          <sz-status-grid-network
            .traffic=${dashboardData.traffic}
            .proxy=${dashboardData.proxy}
            .certificates=${dashboardData.certificates}
          ></sz-status-grid-network>
        </section>

        <section class="section">
          <h2 class="section-title">Infrastructure</h2>
          <sz-status-grid-infra
            ?dnsConfigured=${dashboardData.dnsConfigured}
            ?acmeConfigured=${dashboardData.acmeConfigured}
            .actions=${dashboardData.quickActions}
            @action-click=${(e: CustomEvent) => this.handleQuickAction(e)}
          ></sz-status-grid-infra>
        </section>
      </div>
    `;
  }

  private handleQuickAction(e: CustomEvent) {
    const action = e.detail?.action || e.detail?.label;
    if (action === 'Deploy Service') {
      appRouter.navigateToView('services');
    } else if (action === 'Add Domain') {
      appRouter.navigateToView('network');
    }
  }

  private handlePlatformServiceClick(e: CustomEvent) {
    // Find the platform service type from the click event
    const name = e.detail?.name;
    const ps = this.servicesState.platformServices.find(
      (p) => p.displayName === name,
    );
    if (ps) {
      // Navigate to services tab — the ObViewServices component will pick up the type
      // Store the selected platform type so the services view can open it
      appstate.servicesStatePart.setState({
        ...appstate.servicesStatePart.getState(),
        currentPlatformService: ps,
      });
      appRouter.navigateToView('services');
    }
  }
}
