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

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

@customElement('objst-view-config')
export class ObjstViewConfig extends DeesElement {
  @state()
  accessor configState: appstate.IConfigState = { config: null, clusterHealth: null };

  constructor() {
    super();
    const sub = appstate.configStatePart
      .select((s) => s)
      .subscribe((configState) => {
        this.configState = configState;
      });
    this.rxSubscriptions.push(sub);
  }

  async connectedCallback() {
    super.connectedCallback();
    appstate.configStatePart.dispatchAction(appstate.fetchConfigAction, null);
  }

  public static styles = [
    cssManager.defaultStyles,
    shared.viewHostCss,
    css`
      .sectionSpacer {
        margin-top: 32px;
      }
      .infoPanel {
        margin-top: 32px;
        padding: 24px;
        border-radius: 8px;
        background: ${cssManager.bdTheme('#f5f5f5', '#1a1a2e')};
        border: 1px solid ${cssManager.bdTheme('#e0e0e0', '#2a2a4a')};
      }
      .infoPanel h2 {
        margin: 0 0 16px 0;
        font-size: 18px;
        font-weight: 600;
        color: ${cssManager.bdTheme('#333', '#ccc')};
      }
      .infoPanel p {
        margin: 0 0 16px 0;
        font-size: 14px;
        color: ${cssManager.bdTheme('#666', '#999')};
        line-height: 1.5;
      }
      .infoPanel .row {
        display: flex;
        align-items: center;
        margin-bottom: 8px;
        font-size: 14px;
      }
      .infoPanel .label {
        min-width: 260px;
        font-family: monospace;
        font-weight: 500;
        color: ${cssManager.bdTheme('#1565c0', '#64b5f6')};
        padding: 4px 8px;
        border-radius: 4px;
        background: ${cssManager.bdTheme('#e3f2fd', '#1a237e30')};
      }
      .infoPanel .value {
        color: ${cssManager.bdTheme('#666', '#999')};
        margin-left: 12px;
      }
      .driveList {
        margin-top: 16px;
      }
      .driveList .driveItem {
        display: flex;
        align-items: center;
        margin-bottom: 8px;
        font-size: 14px;
      }
      .driveList .driveIndex {
        width: 32px;
        height: 32px;
        border-radius: 6px;
        background: ${cssManager.bdTheme('#e8eaf6', '#1a237e40')};
        color: ${cssManager.bdTheme('#3f51b5', '#7986cb')};
        display: flex;
        align-items: center;
        justify-content: center;
        font-weight: 600;
        font-size: 13px;
        margin-right: 12px;
      }
      .driveList .drivePath {
        font-family: monospace;
        color: ${cssManager.bdTheme('#333', '#e0e0e0')};
        padding: 6px 12px;
        border-radius: 4px;
        background: ${cssManager.bdTheme('#e8e8e8', '#252540')};
      }
      .driveList .driveStatus {
        margin-left: 12px;
        padding: 4px 8px;
        border-radius: 999px;
        font-size: 12px;
        font-weight: 600;
        color: ${cssManager.bdTheme('#1b5e20', '#a5d6a7')};
        background: ${cssManager.bdTheme('#e8f5e9', '#1b5e2030')};
      }
      .driveList .driveMeta {
        margin-left: 12px;
        color: ${cssManager.bdTheme('#666', '#999')};
        font-size: 13px;
      }
    `,
  ];

  public render(): TemplateResult {
    const config = this.configState.config;
    const clusterHealth = this.configState.clusterHealth;

    const serverTiles: IStatsTile[] = [
      {
        id: 'objstPort',
        title: 'Storage API Port',
        value: config?.objstPort ?? '--',
        type: 'number',
        icon: 'lucide:network',
        color: '#2196f3',
      },
      {
        id: 'uiPort',
        title: 'UI Port',
        value: config?.uiPort ?? '--',
        type: 'number',
        icon: 'lucide:monitor',
        color: '#00bcd4',
      },
      {
        id: 'region',
        title: 'Region',
        value: config?.region ?? '--',
        type: 'text',
        icon: 'lucide:globe',
        color: '#607d8b',
      },
      {
        id: 'storageDir',
        title: 'Storage Directory',
        value: config?.storageDirectory ?? '--',
        type: 'text',
        icon: 'lucide:hardDrive',
        color: '#9c27b0',
      },
      {
        id: 'auth',
        title: 'Authentication',
        value: config?.authEnabled ? 'Enabled' : 'Disabled',
        type: 'text',
        icon: 'lucide:shield',
        color: config?.authEnabled ? '#4caf50' : '#f44336',
      },
      {
        id: 'cors',
        title: 'CORS',
        value: config?.corsEnabled ? 'Enabled' : 'Disabled',
        type: 'text',
        icon: 'lucide:globe2',
        color: config?.corsEnabled ? '#4caf50' : '#ff9800',
      },
    ];

    const clusterEnabled = clusterHealth?.enabled ?? config?.clusterEnabled ?? false;
    const clusterTiles: IStatsTile[] = [
      {
        id: 'clusterStatus',
        title: 'Cluster Status',
        value: clusterEnabled ? 'Enabled' : 'Disabled',
        type: 'text',
        icon: 'lucide:network',
        color: clusterEnabled ? '#4caf50' : '#ff9800',
      },
      {
        id: 'nodeId',
        title: 'Node ID',
        value: clusterHealth?.nodeId || config?.clusterNodeId || '(auto)',
        type: 'text',
        icon: 'lucide:fingerprint',
        color: '#607d8b',
      },
      {
        id: 'quicPort',
        title: 'QUIC Port',
        value: config?.clusterQuicPort ?? 4433,
        type: 'number',
        icon: 'lucide:radio',
        color: '#00bcd4',
      },
      {
        id: 'seedNodes',
        title: 'Seed Nodes',
        value: config?.clusterSeedNodes?.length ?? 0,
        type: 'number',
        icon: 'lucide:gitBranch',
        color: '#3f51b5',
        description: config?.clusterSeedNodes?.length
          ? config.clusterSeedNodes.join(', ')
          : 'No seed nodes configured',
      },
      {
        id: 'heartbeatInterval',
        title: 'Heartbeat Interval',
        value: `${config?.clusterHeartbeatIntervalMs ?? 5000}ms`,
        type: 'text',
        icon: 'lucide:heartPulse',
        color: '#e91e63',
      },
      {
        id: 'heartbeatTimeout',
        title: 'Heartbeat Timeout',
        value: `${config?.clusterHeartbeatTimeoutMs ?? 30000}ms`,
        type: 'text',
        icon: 'lucide:timer',
        color: '#ff5722',
      },
      {
        id: 'quorum',
        title: 'Quorum',
        value: clusterHealth?.enabled
          ? clusterHealth.quorumHealthy ? 'Healthy' : 'Degraded'
          : 'Standalone',
        type: 'text',
        icon: 'lucide:activity',
        color: clusterHealth?.quorumHealthy ? '#4caf50' : '#ff9800',
      },
      {
        id: 'peers',
        title: 'Peers',
        value: clusterHealth?.peers?.length ?? 0,
        type: 'number',
        icon: 'lucide:share2',
        color: '#3f51b5',
      },
    ];

    const erasureTiles: IStatsTile[] = [
      {
        id: 'dataShards',
        title: 'Data Shards',
        value: clusterHealth?.erasure?.dataShards ?? config?.erasureDataShards ?? 4,
        type: 'number',
        icon: 'lucide:layers',
        color: '#2196f3',
      },
      {
        id: 'parityShards',
        title: 'Parity Shards',
        value: clusterHealth?.erasure?.parityShards ?? config?.erasureParityShards ?? 2,
        type: 'number',
        icon: 'lucide:shieldCheck',
        color: '#4caf50',
      },
      {
        id: 'chunkSize',
        title: 'Chunk Size',
        value: this.formatBytes(
          clusterHealth?.erasure?.chunkSizeBytes ?? config?.erasureChunkSizeBytes ?? 4194304,
        ),
        type: 'text',
        icon: 'lucide:puzzle',
        color: '#9c27b0',
        description: `${clusterHealth?.erasure?.dataShards ?? config?.erasureDataShards ?? 4}+${
          clusterHealth?.erasure?.parityShards ?? config?.erasureParityShards ?? 2
        }`,
      },
    ];

    const drivePaths = clusterHealth?.drives?.length
      ? clusterHealth.drives.map((drive) => drive.path)
      : config?.drivePaths?.length
      ? config.drivePaths
      : config?.storageDirectory
      ? [config.storageDirectory]
      : ['/data'];

    const driveTiles: IStatsTile[] = [
      {
        id: 'driveCount',
        title: 'Drive Count',
        value: clusterHealth?.drives?.length ?? drivePaths.length,
        type: 'number',
        icon: 'lucide:hardDrive',
        color: '#3f51b5',
      },
    ];

    const refreshAction = {
      name: 'Refresh',
      iconName: 'lucide:refreshCw',
      action: async () => {
        await appstate.configStatePart.dispatchAction(appstate.fetchConfigAction, null);
      },
    };

    return html`
      <objst-sectionheading>Server Configuration</objst-sectionheading>
      <dees-statsgrid
        .tiles="${serverTiles}"
        .gridActions="${[refreshAction]}"
      ></dees-statsgrid>

      <div class="sectionSpacer">
        <objst-sectionheading>Cluster Configuration</objst-sectionheading>
      </div>
      <dees-statsgrid .tiles="${clusterTiles}"></dees-statsgrid>

      ${clusterEnabled
        ? html`
          <div class="sectionSpacer">
            <objst-sectionheading>Erasure Coding</objst-sectionheading>
          </div>
          <dees-statsgrid .tiles="${erasureTiles}"></dees-statsgrid>
        `
        : ''}

      <div class="sectionSpacer">
        <objst-sectionheading>Storage Drives</objst-sectionheading>
      </div>
      <dees-statsgrid .tiles="${driveTiles}"></dees-statsgrid>
      <div class="driveList">
        ${(clusterHealth?.drives?.length
          ? clusterHealth.drives
          : drivePaths.map((path, index) => ({ path, index, status: 'configured' }))).map((
            drive,
            i,
          ) =>
            html`
              <div class="driveItem">
                <div class="driveIndex">${i + 1}</div>
                <span class="drivePath">${drive.path}</span>
                <span class="driveStatus">${drive.status}</span>
                ${drive.usedBytes !== undefined && drive.totalBytes !== undefined
                  ? html`
                    <span class="driveMeta">${this.formatBytes(drive.usedBytes)} / ${this
                      .formatBytes(drive.totalBytes)}</span>
                  `
                  : ''}
              </div>
            `
          )}
      </div>

      <div class="infoPanel">
        <h2>Configuration Reference</h2>
        <p>
          Cluster and drive settings are applied at server startup. To change them, set the environment
          variables and restart the server.
        </p>
        <div class="row">
          <span class="label">OBJST_CLUSTER_ENABLED</span><span class="value"
          >Enable clustering (true/false)</span>
        </div>
        <div class="row">
          <span class="label">OBJST_CLUSTER_NODE_ID</span><span class="value"
          >Unique node identifier</span>
        </div>
        <div class="row">
          <span class="label">OBJST_CLUSTER_QUIC_PORT</span><span class="value"
          >QUIC transport port (default: 4433)</span>
        </div>
        <div class="row">
          <span class="label">OBJST_CLUSTER_SEED_NODES</span><span class="value"
          >Comma-separated seed node addresses</span>
        </div>
        <div class="row">
          <span class="label">OBJST_DRIVE_PATHS</span><span class="value"
          >Comma-separated drive mount paths</span>
        </div>
        <div class="row">
          <span class="label">OBJST_ERASURE_DATA_SHARDS</span><span class="value"
          >Data shards for erasure coding (default: 4)</span>
        </div>
        <div class="row">
          <span class="label">OBJST_ERASURE_PARITY_SHARDS</span><span class="value"
          >Parity shards for erasure coding (default: 2)</span>
        </div>
        <div class="row">
          <span class="label">OBJST_ERASURE_CHUNK_SIZE</span><span class="value"
          >Chunk size in bytes (default: 4194304)</span>
        </div>
        <div class="row">
          <span class="label">OBJST_HEARTBEAT_INTERVAL_MS</span><span class="value"
          >Heartbeat interval in ms (default: 5000)</span>
        </div>
        <div class="row">
          <span class="label">OBJST_HEARTBEAT_TIMEOUT_MS</span><span class="value"
          >Heartbeat timeout in ms (default: 30000)</span>
        </div>
      </div>
    `;
  }

  private formatBytes(bytes: number): string {
    if (bytes === 0) return '0 B';
    const units = ['B', 'KB', 'MB', 'GB', 'TB'];
    const i = Math.floor(Math.log(bytes) / Math.log(1024));
    return `${(bytes / Math.pow(1024, i)).toFixed(i === 0 ? 0 : 1)} ${units[i]}`;
  }
}
