import React from 'react';
import {
  fetchClientMonitoringLogs,
  fetchMonitoringOverview,
  fetchRecentClientErrors,
  type MonitoringClient,
  type MonitoringLogEntry,
  type MonitoringOverview,
} from './apiClientMonitoring';
import { useAuth } from './useAuth';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';
import {
  GridComponent,
  ColumnsDirective,
  ColumnDirective,
  Inject,
  Page,
  Search,
  Sort,
  Toolbar,
} from '@syncfusion/ej2-react-grids';
import { MessageComponent } from '@syncfusion/ej2-react-notifications';
import { DialogComponent } from '@syncfusion/ej2-react-popups';
import './monitoring.css';

const REFRESH_INTERVAL_MS = 15000;
const PRIORITY_REFRESH_INTERVAL_MS = 3000;

const hourOptions = [
  { text: 'Letzte 6 Stunden', value: 6 },
  { text: 'Letzte 24 Stunden', value: 24 },
  { text: 'Letzte 72 Stunden', value: 72 },
  { text: 'Letzte 168 Stunden', value: 168 },
];

const logLevelOptions = [
  { text: 'Alle Logs', value: 'ALL' },
  { text: 'ERROR', value: 'ERROR' },
  { text: 'WARN', value: 'WARN' },
  { text: 'INFO', value: 'INFO' },
  { text: 'DEBUG', value: 'DEBUG' },
];

const statusPalette: Record<string, { label: string; color: string; background: string }> = {
  healthy: { label: 'Stabil', color: '#166534', background: '#dcfce7' },
  warning: { label: 'Warnung', color: '#92400e', background: '#fef3c7' },
  critical: { label: 'Kritisch', color: '#991b1b', background: '#fee2e2' },
  offline: { label: 'Offline', color: '#334155', background: '#e2e8f0' },
};

function parseUtcDate(value?: string | null): Date | null {
  if (!value) return null;
  const trimmed = value.trim();
  if (!trimmed) return null;

  const hasTimezone = /[zZ]$|[+-]\d{2}:?\d{2}$/.test(trimmed);
  const utcValue = hasTimezone ? trimmed : `${trimmed}Z`;
  const parsed = new Date(utcValue);
  if (Number.isNaN(parsed.getTime())) return null;
  return parsed;
}

function formatTimestamp(value?: string | null): string {
  if (!value) return 'Keine Daten';
  const date = parseUtcDate(value);
  if (!date) return value;
  return date.toLocaleString('de-DE');
}

function formatRelative(value?: string | null): string {
  if (!value) return 'Keine Daten';
  const date = parseUtcDate(value);
  if (!date) return 'Unbekannt';

  const diffMs = Date.now() - date.getTime();
  const diffMinutes = Math.floor(diffMs / 60000);
  const diffHours = Math.floor(diffMinutes / 60);
  const diffDays = Math.floor(diffHours / 24);

  if (diffMinutes < 1) return 'gerade eben';
  if (diffMinutes < 60) return `vor ${diffMinutes} Min.`;
  if (diffHours < 24) return `vor ${diffHours} Std.`;
  return `vor ${diffDays} Tag${diffDays === 1 ? '' : 'en'}`;
}

function statusBadge(status: string) {
  const palette = statusPalette[status] || statusPalette.offline;
  return (
    <span
      className="monitoring-status-badge"
      style={{ color: palette.color, backgroundColor: palette.background }}
    >
      {palette.label}
    </span>
  );
}

function screenshotTypeBadge(type?: string | null, hasPriority = false) {
  const normalized = (type || 'periodic').toLowerCase();
  const map: Record<string, { label: string; className: string }> = {
    periodic: { label: 'Periodisch', className: 'monitoring-shot-type-periodic' },
    event_start: { label: 'Event-Start', className: 'monitoring-shot-type-event' },
    event_stop: { label: 'Event-Stopp', className: 'monitoring-shot-type-event' },
  };

  const info = map[normalized] || map.periodic;
  const classes = `monitoring-shot-type ${info.className}${hasPriority ? ' monitoring-shot-type-active' : ''}`;
  return <span className={classes}>{info.label}</span>;
}

function renderMetricCard(title: string, value: number, subtitle: string, accent: string) {
  return (
    <div className="e-card monitoring-metric-card" style={{ borderTop: `4px solid ${accent}` }}>
      <div className="e-card-content monitoring-metric-content">
        <div className="monitoring-metric-title">{title}</div>
        <div className="monitoring-metric-value">{value}</div>
        <div className="monitoring-metric-subtitle">{subtitle}</div>
      </div>
    </div>
  );
}

function renderContext(context?: Record<string, unknown>): string {
  if (!context || Object.keys(context).length === 0) {
    return 'Kein Kontext vorhanden';
  }
  try {
    return JSON.stringify(context, null, 2);
  } catch {
    return 'Kontext konnte nicht formatiert werden';
  }
}

function buildScreenshotUrl(client: MonitoringClient, overviewTimestamp?: string | null): string {
  const refreshKey = client.lastScreenshotHash || client.lastScreenshotAnalyzed || overviewTimestamp;
  if (!refreshKey) {
    return client.screenshotUrl;
  }

  const separator = client.screenshotUrl.includes('?') ? '&' : '?';
  return `${client.screenshotUrl}${separator}v=${encodeURIComponent(refreshKey)}`;
}

const MonitoringDashboard: React.FC = () => {
  const { user } = useAuth();
  const [hours, setHours] = React.useState<number>(24);
  const [logLevel, setLogLevel] = React.useState<string>('ALL');
  const [overview, setOverview] = React.useState<MonitoringOverview | null>(null);
  const [recentErrors, setRecentErrors] = React.useState<MonitoringLogEntry[]>([]);
  const [clientLogs, setClientLogs] = React.useState<MonitoringLogEntry[]>([]);
  const [selectedClientUuid, setSelectedClientUuid] = React.useState<string | null>(null);
  const [loading, setLoading] = React.useState<boolean>(true);
  const [error, setError] = React.useState<string | null>(null);
  const [logsLoading, setLogsLoading] = React.useState<boolean>(false);
  const [screenshotErrored, setScreenshotErrored] = React.useState<boolean>(false);
  const selectedClientUuidRef = React.useRef<string | null>(null);
  const [selectedLogEntry, setSelectedLogEntry] = React.useState<MonitoringLogEntry | null>(null);

  const selectedClient = React.useMemo<MonitoringClient | null>(() => {
    if (!overview || !selectedClientUuid) return null;
    return overview.clients.find(client => client.uuid === selectedClientUuid) || null;
  }, [overview, selectedClientUuid]);

  const selectedClientScreenshotUrl = React.useMemo<string | null>(() => {
    if (!selectedClient) return null;
    return buildScreenshotUrl(selectedClient, overview?.timestamp || null);
  }, [selectedClient, overview?.timestamp]);

  React.useEffect(() => {
    selectedClientUuidRef.current = selectedClientUuid;
  }, [selectedClientUuid]);

  const loadOverview = React.useCallback(async (requestedHours: number, preserveSelection = true) => {
    setLoading(true);
    setError(null);
    try {
      const [overviewData, errorsData] = await Promise.all([
        fetchMonitoringOverview(requestedHours),
        fetchRecentClientErrors(25),
      ]);
      setOverview(overviewData);
      setRecentErrors(errorsData);

      const currentSelection = selectedClientUuidRef.current;
      const nextSelectedUuid =
        preserveSelection && currentSelection && overviewData.clients.some(client => client.uuid === currentSelection)
          ? currentSelection
          : overviewData.clients[0]?.uuid || null;

      setSelectedClientUuid(nextSelectedUuid);
      setScreenshotErrored(false);
    } catch (loadError) {
      setError(loadError instanceof Error ? loadError.message : 'Monitoring-Daten konnten nicht geladen werden');
    } finally {
      setLoading(false);
    }
  }, []);

  React.useEffect(() => {
    loadOverview(hours, false);
  }, [hours, loadOverview]);

  React.useEffect(() => {
    const hasActivePriorityScreenshots = (overview?.summary.activePriorityScreenshots || 0) > 0;
    const intervalMs = hasActivePriorityScreenshots ? PRIORITY_REFRESH_INTERVAL_MS : REFRESH_INTERVAL_MS;
    const intervalId = window.setInterval(() => {
      loadOverview(hours);
    }, intervalMs);

    return () => window.clearInterval(intervalId);
  }, [hours, loadOverview, overview?.summary.activePriorityScreenshots]);

  React.useEffect(() => {
    if (!selectedClientUuid) {
      setClientLogs([]);
      return;
    }

    let active = true;
    const loadLogs = async () => {
      setLogsLoading(true);
      try {
        const logs = await fetchClientMonitoringLogs(selectedClientUuid, { level: logLevel, limit: 100 });
        if (active) {
          setClientLogs(logs);
        }
      } catch (loadError) {
        if (active) {
          setClientLogs([]);
          setError(loadError instanceof Error ? loadError.message : 'Client-Logs konnten nicht geladen werden');
        }
      } finally {
        if (active) {
          setLogsLoading(false);
        }
      }
    };

    loadLogs();
    return () => {
      active = false;
    };
  }, [selectedClientUuid, logLevel]);

  React.useEffect(() => {
    setScreenshotErrored(false);
  }, [selectedClientUuid]);

  if (!user || user.role !== 'superadmin') {
    return (
      <MessageComponent severity="Error" content="Dieses Monitoring-Dashboard ist nur für Superadministratoren sichtbar." />
    );
  }

  const clientGridData = (overview?.clients || []).map(client => ({
    ...client,
    displayName: client.description || client.hostname || client.uuid,
    lastAliveDisplay: formatTimestamp(client.lastAlive),
    currentProcessDisplay: client.currentProcess || 'kein Prozess',
    processStatusDisplay: client.processStatus || 'unbekannt',
    errorCount: client.logCounts24h.error,
    warnCount: client.logCounts24h.warn,
  }));

  return (
    <div className="monitoring-page">
      <div className="monitoring-header-row">
        <div>
          <h2 className="monitoring-title">Monitor-Dashboard</h2>
          <p className="monitoring-subtitle">
            Live-Zustand der Infoscreen-Clients, Prozessstatus und zentrale Fehlerprotokolle.
          </p>
        </div>
        <div className="monitoring-toolbar">
          <div className="monitoring-toolbar-field">
            <label>Zeitraum</label>
            <DropDownListComponent
              dataSource={hourOptions}
              fields={{ text: 'text', value: 'value' }}
              value={hours}
              change={(args: { value: number }) => setHours(Number(args.value))}
            />
          </div>
          <ButtonComponent cssClass="e-primary" onClick={() => loadOverview(hours)} disabled={loading}>
            Aktualisieren
          </ButtonComponent>
        </div>
      </div>

      {error && <MessageComponent severity="Error" content={error} />}

      {overview && (
        <div className="monitoring-meta-row">
          <span>Stand: {formatTimestamp(overview.timestamp)}</span>
          <span>Alive-Fenster: {overview.gracePeriodSeconds} Sekunden</span>
          <span>Betrachtungszeitraum: {overview.periodHours} Stunden</span>
        </div>
      )}

      <div className="monitoring-summary-grid">
        {renderMetricCard('Clients gesamt', overview?.summary.totalClients || 0, 'Registrierte Displays', '#7c3aed')}
        {renderMetricCard('Online', overview?.summary.onlineClients || 0, 'Heartbeat innerhalb der Grace-Periode', '#15803d')}
        {renderMetricCard('Warnungen', overview?.summary.warningClients || 0, 'Warn-Logs oder Übergangszustände', '#d97706')}
        {renderMetricCard('Kritisch', overview?.summary.criticalClients || 0, 'Crashs oder Fehler-Logs', '#dc2626')}
        {renderMetricCard('Offline', overview?.summary.offlineClients || 0, 'Keine frischen Signale', '#475569')}
        {renderMetricCard('Prioritäts-Screens', overview?.summary.activePriorityScreenshots || 0, 'Event-Start/Stop aktiv', '#ea580c')}
        {renderMetricCard('Fehler-Logs', overview?.summary.errorLogs || 0, 'Im gewählten Zeitraum', '#b91c1c')}
      </div>

      {loading && !overview ? (
        <MessageComponent severity="Info" content="Monitoring-Daten werden geladen ..." />
      ) : (
        <div className="monitoring-main-grid">
          <div className="monitoring-panel monitoring-clients-panel">
            <div className="monitoring-panel-header">
              <h3>Client-Zustand</h3>
              <span>{overview?.clients.length || 0} Einträge</span>
            </div>
            <GridComponent
              dataSource={clientGridData}
              allowPaging={true}
              pageSettings={{ pageSize: 10 }}
              allowSorting={true}
              toolbar={['Search']}
              height={460}
              rowSelected={(args: { data: MonitoringClient }) => {
                setSelectedClientUuid(args.data.uuid);
              }}
            >
              <ColumnsDirective>
                <ColumnDirective
                  field="status"
                  headerText="Status"
                  width="120"
                  template={(props: MonitoringClient) => statusBadge(props.status)}
                />
                <ColumnDirective field="displayName" headerText="Client" width="190" />
                <ColumnDirective field="groupName" headerText="Gruppe" width="150" />
                <ColumnDirective field="currentProcessDisplay" headerText="Prozess" width="130" />
                <ColumnDirective field="processStatusDisplay" headerText="Prozessstatus" width="130" />
                <ColumnDirective field="errorCount" headerText="ERROR" textAlign="Right" width="90" />
                <ColumnDirective field="warnCount" headerText="WARN" textAlign="Right" width="90" />
                <ColumnDirective field="lastAliveDisplay" headerText="Letztes Signal" width="170" />
              </ColumnsDirective>
              <Inject services={[Page, Search, Sort, Toolbar]} />
            </GridComponent>
          </div>

          <div className="monitoring-sidebar-column">
            <div className="e-card monitoring-detail-card">
              <div className="e-card-header">
                <div className="e-card-header-caption">
                  <div className="e-card-title">Aktiver Client</div>
                </div>
              </div>
              <div className="e-card-content">
                {selectedClient ? (
                  <div className="monitoring-detail-list">
                    <div className="monitoring-detail-row">
                      <span>Name</span>
                      <strong>{selectedClient.description || selectedClient.hostname || selectedClient.uuid}</strong>
                    </div>
                    <div className="monitoring-detail-row">
                      <span>Status</span>
                      <strong>{statusBadge(selectedClient.status)}</strong>
                    </div>
                    <div className="monitoring-detail-row">
                      <span>UUID</span>
                      <strong className="monitoring-mono">{selectedClient.uuid}</strong>
                    </div>
                    <div className="monitoring-detail-row">
                      <span>Raumgruppe</span>
                      <strong>{selectedClient.groupName || 'Nicht zugeordnet'}</strong>
                    </div>
                    <div className="monitoring-detail-row">
                      <span>Prozess</span>
                      <strong>{selectedClient.currentProcess || 'kein Prozess'}</strong>
                    </div>
                    <div className="monitoring-detail-row">
                      <span>PID</span>
                      <strong>{selectedClient.processPid || 'keine PID'}</strong>
                    </div>
                    <div className="monitoring-detail-row">
                      <span>Event-ID</span>
                      <strong>{selectedClient.currentEventId || 'keine Zuordnung'}</strong>
                    </div>
                    <div className="monitoring-detail-row">
                      <span>Letztes Signal</span>
                      <strong>{formatRelative(selectedClient.lastAlive)}</strong>
                    </div>
                    <div className="monitoring-detail-row">
                      <span>Bildschirmstatus</span>
                      <strong>{selectedClient.screenHealthStatus || 'UNKNOWN'}</strong>
                    </div>
                    <div className="monitoring-detail-row">
                      <span>Letzte Analyse</span>
                      <strong>{formatTimestamp(selectedClient.lastScreenshotAnalyzed)}</strong>
                    </div>
                    <div className="monitoring-detail-row">
                      <span>Screenshot-Typ</span>
                      <strong>
                        {screenshotTypeBadge(
                          selectedClient.latestScreenshotType,
                          !!selectedClient.hasActivePriorityScreenshot
                        )}
                      </strong>
                    </div>
                    {selectedClient.priorityScreenshotReceivedAt && (
                      <div className="monitoring-detail-row">
                        <span>Priorität empfangen</span>
                        <strong>{formatTimestamp(selectedClient.priorityScreenshotReceivedAt)}</strong>
                      </div>
                    )}
                  </div>
                ) : (
                  <MessageComponent severity="Info" content="Wählen Sie links einen Client aus." />
                )}
              </div>
            </div>

            <div className="e-card monitoring-detail-card">
              <div className="e-card-header">
                <div className="e-card-header-caption">
                  <div className="e-card-title">Der letzte Screenshot</div>
                </div>
              </div>
              <div className="e-card-content">
                {selectedClient ? (
                  <>
                    {screenshotErrored ? (
                      <MessageComponent severity="Warning" content="Für diesen Client liegt noch kein Screenshot vor." />
                    ) : (
                      <img
                        src={selectedClientScreenshotUrl || selectedClient.screenshotUrl}
                        alt={`Screenshot ${selectedClient.uuid}`}
                        className="monitoring-screenshot"
                        onError={() => setScreenshotErrored(true)}
                      />
                    )}
                    <div className="monitoring-screenshot-meta">
                      <span>Empfangen: {formatTimestamp(selectedClient.lastScreenshotAnalyzed)}</span>
                      <span>
                        Typ:{' '}
                        {screenshotTypeBadge(
                          selectedClient.latestScreenshotType,
                          !!selectedClient.hasActivePriorityScreenshot
                        )}
                      </span>
                    </div>
                  </>
                ) : (
                  <MessageComponent severity="Info" content="Kein Client ausgewählt." />
                )}
              </div>
            </div>

            <div className="e-card monitoring-detail-card">
              <div className="e-card-header">
                <div className="e-card-header-caption">
                  <div className="e-card-title">Letzter Fehler</div>
                </div>
              </div>
              <div className="e-card-content">
                {selectedClient?.latestError ? (
                  <div className="monitoring-error-box">
                    <div className="monitoring-error-time">{formatTimestamp(selectedClient.latestError.timestamp)}</div>
                    <div className="monitoring-error-message">{selectedClient.latestError.message}</div>
                  </div>
                ) : (
                  <MessageComponent severity="Success" content="Kein ERROR-Log für den ausgewählten Client gefunden." />
                )}
              </div>
            </div>
          </div>
        </div>
      )}

      <div className="monitoring-lower-grid">
        <div className="monitoring-panel">
          <div className="monitoring-panel-header monitoring-panel-header-stacked">
            <div>
              <h3>Client-Logs</h3>
              <span>{selectedClient ? `Client ${selectedClient.uuid}` : 'Kein Client ausgewählt'}</span>
            </div>
            <div className="monitoring-toolbar-field monitoring-toolbar-field-compact">
              <label>Level</label>
              <DropDownListComponent
                dataSource={logLevelOptions}
                fields={{ text: 'text', value: 'value' }}
                value={logLevel}
                change={(args: { value: string }) => setLogLevel(String(args.value))}
              />
            </div>
          </div>
          {logsLoading && <MessageComponent severity="Info" content="Client-Logs werden geladen ..." />}
          <GridComponent
            dataSource={clientLogs}
            allowPaging={true}
            pageSettings={{ pageSize: 8 }}
            allowSorting={true}
            height={320}
            rowSelected={(args: { data: MonitoringLogEntry }) => {
              setSelectedLogEntry(args.data);
            }}
          >
            <ColumnsDirective>
              <ColumnDirective field="timestamp" headerText="Zeit" width="180" template={(props: MonitoringLogEntry) => formatTimestamp(props.timestamp)} />
              <ColumnDirective field="level" headerText="Level" width="90" />
              <ColumnDirective field="message" headerText="Nachricht" width="360" />
            </ColumnsDirective>
            <Inject services={[Page, Sort]} />
          </GridComponent>
        </div>

        <div className="monitoring-panel">
          <div className="monitoring-panel-header">
            <h3>Letzte Fehler systemweit</h3>
            <span>{recentErrors.length} Einträge</span>
          </div>
          <GridComponent dataSource={recentErrors} allowPaging={true} pageSettings={{ pageSize: 8 }} allowSorting={true} height={320}>
            <ColumnsDirective>
              <ColumnDirective field="timestamp" headerText="Zeit" width="180" template={(props: MonitoringLogEntry) => formatTimestamp(props.timestamp)} />
              <ColumnDirective field="client_uuid" headerText="Client" width="220" />
              <ColumnDirective field="message" headerText="Nachricht" width="360" />
            </ColumnsDirective>
            <Inject services={[Page, Sort]} />
          </GridComponent>
        </div>
      </div>

      <DialogComponent
        isModal={true}
        visible={!!selectedLogEntry}
        width="860px"
        minHeight="420px"
        header="Log-Details"
        animationSettings={{ effect: 'None' }}
        buttons={[]}
        showCloseIcon={true}
        close={() => setSelectedLogEntry(null)}
      >
        {selectedLogEntry && (
          <div className="monitoring-log-dialog-body">
            <div className="monitoring-log-dialog-content">
              <div className="monitoring-log-detail-row">
                <span>Zeit</span>
                <strong>{formatTimestamp(selectedLogEntry.timestamp)}</strong>
              </div>
              <div className="monitoring-log-detail-row">
                <span>Level</span>
                <strong>{selectedLogEntry.level || 'Unbekannt'}</strong>
              </div>
              <div className="monitoring-log-detail-row">
                <span>Nachricht</span>
                <strong style={{ whiteSpace: 'normal', textAlign: 'left' }}>{selectedLogEntry.message}</strong>
              </div>
              <div>
                <div className="monitoring-log-context-title">Kontext</div>
                <pre className="monitoring-log-context">{renderContext(selectedLogEntry.context)}</pre>
              </div>
            </div>
            <div className="monitoring-log-dialog-actions">
              <ButtonComponent onClick={() => setSelectedLogEntry(null)}>Schließen</ButtonComponent>
            </div>
          </div>
        )}
      </DialogComponent>
    </div>
  );
};

export default MonitoringDashboard;