import { useState, useEffect, useRef } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import api from '../api/client';

// ============================================================
//  Types
// ============================================================

interface SslCertInfo {
  subject: string;
  issuer: string;
  validFrom: string;
  validTo: string;
  sanList: string[];
  dnsMatch: boolean;
  isExpired: boolean;
  fingerprint: string;
}

interface SslConfig {
  enabled: boolean;
  dnsName: string | null;
  certificate: SslCertInfo | null;
  lastUpdated: string | null;
}

interface DnsCheckResponse {
  resolves: boolean;
  addresses: string[];
  error?: string;
}

interface SslSaveResponse {
  success: boolean;
  config: SslConfig;
  warnings: string[];
}

// ============================================================
//  Styles
// ============================================================

const cardStyle: React.CSSProperties = {
  background: 'var(--color-bg-card)',
  borderRadius: 'var(--radius-md)',
  boxShadow: 'var(--shadow-sm)',
  border: '1px solid var(--color-border)',
  padding: '1.5rem',
  marginBottom: '1.5rem',
};

const labelStyle: React.CSSProperties = {
  fontSize: '0.875rem',
  fontWeight: 500,
  color: 'var(--color-text)',
  marginBottom: '0.375rem',
  display: 'block',
};

const inputStyle: React.CSSProperties = {
  width: '100%',
  padding: '0.625rem 0.75rem',
  border: '1px solid var(--color-border)',
  borderRadius: 'var(--radius-sm)',
  fontSize: '0.9375rem',
  outline: 'none',
  boxSizing: 'border-box',
  background: 'var(--color-bg-card)',
  color: 'var(--color-text)',
};

const btnPrimaryStyle: React.CSSProperties = {
  padding: '0.5rem 1rem',
  background: 'var(--color-primary)',
  color: 'white',
  border: 'none',
  borderRadius: 'var(--radius-sm)',
  fontSize: '0.875rem',
  fontWeight: 600,
  cursor: 'pointer',
};

const btnOutlineStyle: React.CSSProperties = {
  padding: '0.5rem 1rem',
  background: 'transparent',
  border: '1px solid var(--color-border)',
  borderRadius: 'var(--radius-sm)',
  fontSize: '0.875rem',
  cursor: 'pointer',
  color: 'var(--color-text-secondary)',
};

const btnDangerStyle: React.CSSProperties = {
  padding: '0.5rem 1rem',
  background: 'transparent',
  border: '1px solid #fecaca',
  borderRadius: 'var(--radius-sm)',
  fontSize: '0.875rem',
  cursor: 'pointer',
  color: 'var(--color-error)',
};

const badgeStyle = (bg: string, color: string): React.CSSProperties => ({
  display: 'inline-block',
  padding: '0.125rem 0.5rem',
  borderRadius: '9999px',
  fontSize: '0.75rem',
  fontWeight: 500,
  background: bg,
  color,
});

const uploadZoneStyle: React.CSSProperties = {
  border: '2px dashed var(--color-border)',
  borderRadius: 'var(--radius-sm)',
  padding: '1rem',
  textAlign: 'center',
  cursor: 'pointer',
  transition: 'border-color 0.15s',
  background: 'var(--color-bg)',
  fontSize: '0.875rem',
  color: 'var(--color-text-muted)',
};

const infoGridStyle: React.CSSProperties = {
  display: 'grid',
  gridTemplateColumns: '160px 1fr',
  gap: '0.5rem 1rem',
  fontSize: '0.875rem',
};

// ============================================================
//  Helpers
// ============================================================

function formatDate(iso: string): string {
  return new Date(iso).toLocaleDateString('de-DE', {
    day: '2-digit',
    month: '2-digit',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  });
}

function daysUntil(iso: string): number {
  const diff = new Date(iso).getTime() - Date.now();
  return Math.ceil(diff / (1000 * 60 * 60 * 24));
}

// ============================================================
//  Component
// ============================================================

export function AdminSslPage() {
  const queryClient = useQueryClient();

  // Current config from backend
  const { data: config, isLoading } = useQuery<SslConfig>({
    queryKey: ['settings', 'ssl'],
    queryFn: async () => {
      const res = await api.get<SslConfig>('/settings/ssl');
      return res.data;
    },
  });

  // Form state
  const [dnsName, setDnsName] = useState('');
  const [certPem, setCertPem] = useState('');
  const [keyPem, setKeyPem] = useState('');
  const [certFileName, setCertFileName] = useState('');
  const [keyFileName, setKeyFileName] = useState('');

  // DNS check state
  const [dnsCheck, setDnsCheck] = useState<DnsCheckResponse | null>(null);
  const [dnsChecking, setDnsChecking] = useState(false);

  // Feedback
  const [warnings, setWarnings] = useState<string[]>([]);
  const [saveSuccess, setSaveSuccess] = useState(false);
  const [saveError, setSaveError] = useState('');

  // File input refs
  const certInputRef = useRef<HTMLInputElement>(null);
  const keyInputRef = useRef<HTMLInputElement>(null);

  // Init from existing config
  useEffect(() => {
    if (config?.dnsName) {
      setDnsName(config.dnsName);
    }
  }, [config]);

  // ---- DNS Check ----
  const handleDnsCheck = async () => {
    if (!dnsName.trim()) return;
    setDnsChecking(true);
    setDnsCheck(null);
    try {
      const res = await api.post<DnsCheckResponse>('/settings/ssl/check-dns', {
        dnsName: dnsName.trim(),
      });
      setDnsCheck(res.data);
    } catch {
      setDnsCheck({ resolves: false, addresses: [], error: 'Pruefung fehlgeschlagen' });
    } finally {
      setDnsChecking(false);
    }
  };

  // ---- File Handlers ----
  const handleCertFile = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;
    setCertFileName(file.name);
    const reader = new FileReader();
    reader.onload = () => setCertPem(reader.result as string);
    reader.readAsText(file);
  };

  const handleKeyFile = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;
    setKeyFileName(file.name);
    const reader = new FileReader();
    reader.onload = () => setKeyPem(reader.result as string);
    reader.readAsText(file);
  };

  // ---- Save Mutation ----
  const saveMutation = useMutation({
    mutationFn: async (data: { dnsName: string; certificate: string; privateKey: string; enabled: boolean }) => {
      const res = await api.post<SslSaveResponse>('/settings/ssl', data);
      return res.data;
    },
    onSuccess: (data) => {
      queryClient.invalidateQueries({ queryKey: ['settings', 'ssl'] });
      setWarnings(data.warnings);
      setSaveSuccess(true);
      setSaveError('');
      setCertPem('');
      setKeyPem('');
      setCertFileName('');
      setKeyFileName('');
      setTimeout(() => setSaveSuccess(false), 5000);
    },
    onError: (err: unknown) => {
      const msg =
        (err as { response?: { data?: { message?: string } } })?.response?.data
          ?.message ?? 'Fehler beim Speichern';
      setSaveError(msg);
      setSaveSuccess(false);
    },
  });

  // ---- Delete Mutation ----
  const deleteMutation = useMutation({
    mutationFn: async () => {
      await api.delete('/settings/ssl');
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['settings', 'ssl'] });
      setDnsName('');
      setCertPem('');
      setKeyPem('');
      setCertFileName('');
      setKeyFileName('');
      setWarnings([]);
      setDnsCheck(null);
      setSaveSuccess(false);
      setSaveError('');
    },
  });

  const handleSave = () => {
    setSaveError('');
    setWarnings([]);

    if (!dnsName.trim()) {
      setSaveError('DNS-Name ist erforderlich');
      return;
    }

    // Wenn ein bestehendes Cert existiert und keine neuen Dateien hochgeladen → nur DNS-Name aendern
    // Aber PEM-Dateien sind noetig bei Ersteinrichtung
    if (!certPem && !config?.certificate) {
      setSaveError('SSL-Zertifikat ist erforderlich');
      return;
    }
    if (!keyPem && !config?.certificate) {
      setSaveError('Private Key ist erforderlich');
      return;
    }

    saveMutation.mutate({
      dnsName: dnsName.trim(),
      certificate: certPem || '__KEEP_EXISTING__',
      privateKey: keyPem || '__KEEP_EXISTING__',
      enabled: true,
    });
  };

  const handleDelete = () => {
    if (!window.confirm('SSL-Konfiguration wirklich entfernen? Die Plattform ist danach nur noch ueber HTTP / IP erreichbar.')) {
      return;
    }
    deleteMutation.mutate();
  };

  // ---- Render ----

  if (isLoading) {
    return <p style={{ color: 'var(--color-text-muted)', fontSize: '0.875rem' }}>Laden...</p>;
  }

  const hasCert = !!config?.certificate;
  const isActive = !!config?.enabled;
  const certExpDays = config?.certificate?.validTo ? daysUntil(config.certificate.validTo) : null;

  return (
    <div>
      {/* Status Banner */}
      {hasCert && (
        <div style={cardStyle}>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '1rem' }}>
            <h3 style={{ fontSize: '1rem', fontWeight: 600, margin: 0 }}>
              Aktueller Status
            </h3>
            {isActive ? (
              <span style={badgeStyle('#d1fae5', '#065f46')}>Aktiv</span>
            ) : (
              <span style={badgeStyle('#f3f4f6', '#6b7280')}>Inaktiv</span>
            )}
          </div>

          <div style={infoGridStyle}>
            <span style={{ color: 'var(--color-text-muted)' }}>Domain</span>
            <span style={{ fontWeight: 500 }}>
              {config?.dnsName ? (
                <a
                  href={`https://${config.dnsName}`}
                  target="_blank"
                  rel="noopener noreferrer"
                  style={{ color: 'var(--color-primary)', textDecoration: 'none' }}
                >
                  {config.dnsName}
                </a>
              ) : (
                '—'
              )}
            </span>

            <span style={{ color: 'var(--color-text-muted)' }}>Zertifikat</span>
            <span>{config?.certificate?.subject || '—'}</span>

            <span style={{ color: 'var(--color-text-muted)' }}>Aussteller</span>
            <span>{config?.certificate?.issuer || '—'}</span>

            <span style={{ color: 'var(--color-text-muted)' }}>Gueltig bis</span>
            <span>
              {config?.certificate?.validTo ? (
                <>
                  {formatDate(config.certificate.validTo)}
                  {certExpDays !== null && certExpDays <= 30 && certExpDays > 0 && (
                    <span style={badgeStyle('#fef3c7', '#92400e')}>
                      {' '}Noch {certExpDays} Tage
                    </span>
                  )}
                  {config.certificate.isExpired && (
                    <span style={badgeStyle('#fee2e2', '#991b1b')}>
                      {' '}Abgelaufen
                    </span>
                  )}
                </>
              ) : (
                '—'
              )}
            </span>

            <span style={{ color: 'var(--color-text-muted)' }}>SANs</span>
            <span style={{ fontSize: '0.8125rem' }}>
              {config?.certificate?.sanList?.join(', ') || '—'}
            </span>

            <span style={{ color: 'var(--color-text-muted)' }}>Fingerprint</span>
            <span style={{ fontSize: '0.75rem', fontFamily: 'monospace', color: 'var(--color-text-muted)' }}>
              {config?.certificate?.fingerprint || '—'}
            </span>

            {config?.lastUpdated && (
              <>
                <span style={{ color: 'var(--color-text-muted)' }}>Zuletzt aktualisiert</span>
                <span>{formatDate(config.lastUpdated)}</span>
              </>
            )}
          </div>

          {isActive && (
            <div style={{ marginTop: '1rem', paddingTop: '1rem', borderTop: '1px solid var(--color-border)' }}>
              <button
                style={btnDangerStyle}
                onClick={handleDelete}
                disabled={deleteMutation.isPending}
              >
                {deleteMutation.isPending ? 'Entfernen...' : 'SSL deaktivieren'}
              </button>
            </div>
          )}
        </div>
      )}

      {/* Feedback Messages */}
      {saveSuccess && (
        <div
          style={{
            padding: '0.75rem 1rem',
            background: '#d1fae5',
            border: '1px solid #a7f3d0',
            borderRadius: 'var(--radius-sm)',
            color: '#065f46',
            fontSize: '0.875rem',
            marginBottom: '1rem',
          }}
        >
          SSL-Konfiguration erfolgreich gespeichert.
        </div>
      )}

      {saveError && (
        <div
          style={{
            padding: '0.75rem 1rem',
            background: '#fef2f2',
            border: '1px solid #fecaca',
            borderRadius: 'var(--radius-sm)',
            color: 'var(--color-error)',
            fontSize: '0.875rem',
            marginBottom: '1rem',
          }}
        >
          {saveError}
        </div>
      )}

      {warnings.length > 0 && (
        <div
          style={{
            padding: '0.75rem 1rem',
            background: '#fffbeb',
            border: '1px solid #fde68a',
            borderRadius: 'var(--radius-sm)',
            color: '#92400e',
            fontSize: '0.875rem',
            marginBottom: '1rem',
          }}
        >
          <strong>Hinweise:</strong>
          <ul style={{ margin: '0.5rem 0 0', paddingLeft: '1.25rem' }}>
            {warnings.map((w, i) => (
              <li key={i}>{w}</li>
            ))}
          </ul>
        </div>
      )}

      {/* DNS Name Section */}
      <div style={cardStyle}>
        <h3 style={{ fontSize: '1rem', fontWeight: 600, marginBottom: '1rem' }}>
          1. DNS-Name konfigurieren
        </h3>
        <p style={{ fontSize: '0.8125rem', color: 'var(--color-text-muted)', marginBottom: '1rem' }}>
          Erstellen Sie einen DNS A-Record, der auf die Server-IP zeigt.
          Tragen Sie anschliessend den Domainnamen hier ein.
        </p>

        <div style={{ marginBottom: '0.75rem' }}>
          <label style={labelStyle}>DNS-Name</label>
          <div style={{ display: 'flex', gap: '0.5rem' }}>
            <input
              style={{ ...inputStyle, flex: 1 }}
              value={dnsName}
              onChange={(e) => {
                setDnsName(e.target.value);
                setDnsCheck(null);
              }}
              placeholder="insight.firma.de"
            />
            <button
              style={btnOutlineStyle}
              onClick={handleDnsCheck}
              disabled={!dnsName.trim() || dnsChecking}
            >
              {dnsChecking ? 'Pruefe...' : 'DNS pruefen'}
            </button>
          </div>
        </div>

        {dnsCheck && (
          <div
            style={{
              padding: '0.5rem 0.75rem',
              borderRadius: 'var(--radius-sm)',
              fontSize: '0.8125rem',
              background: dnsCheck.resolves ? '#d1fae5' : '#fef3c7',
              color: dnsCheck.resolves ? '#065f46' : '#92400e',
              display: 'flex',
              alignItems: 'center',
              gap: '0.5rem',
            }}
          >
            <span style={{ fontSize: '1rem' }}>{dnsCheck.resolves ? '\u2713' : '\u26A0'}</span>
            {dnsCheck.resolves ? (
              <span>
                Aufgeloest: {dnsCheck.addresses.join(', ')}
              </span>
            ) : (
              <span>
                Nicht aufgeloest. {dnsCheck.error || 'Bitte DNS A-Record pruefen.'}
              </span>
            )}
          </div>
        )}
      </div>

      {/* Certificate Upload Section */}
      <div style={cardStyle}>
        <h3 style={{ fontSize: '1rem', fontWeight: 600, marginBottom: '1rem' }}>
          2. SSL-Zertifikat hochladen
        </h3>
        <p style={{ fontSize: '0.8125rem', color: 'var(--color-text-muted)', marginBottom: '1rem' }}>
          Laden Sie Ihr SSL-Zertifikat und den zugehoerigen Private Key im PEM-Format hoch.
          {hasCert && ' Lassen Sie die Felder leer, um das bestehende Zertifikat zu behalten.'}
        </p>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1rem', marginBottom: '1rem' }}>
          {/* Cert Upload */}
          <div>
            <label style={labelStyle}>
              Zertifikat (.pem, .crt, .cer) {!hasCert && '*'}
            </label>
            <input
              ref={certInputRef}
              type="file"
              accept=".pem,.crt,.cer"
              style={{ display: 'none' }}
              onChange={handleCertFile}
            />
            <div
              style={{
                ...uploadZoneStyle,
                borderColor: certPem ? 'var(--color-primary)' : undefined,
                color: certPem ? 'var(--color-primary)' : undefined,
              }}
              onClick={() => certInputRef.current?.click()}
            >
              {certPem ? (
                <>
                  <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" style={{ verticalAlign: 'middle', marginRight: '0.375rem' }}>
                    <path d="M5 8l2 2 4-4" strokeLinecap="round" strokeLinejoin="round" />
                    <circle cx="8" cy="8" r="6" />
                  </svg>
                  {certFileName}
                </>
              ) : (
                'Zertifikat-Datei auswaehlen'
              )}
            </div>
          </div>

          {/* Key Upload */}
          <div>
            <label style={labelStyle}>
              Private Key (.pem, .key) {!hasCert && '*'}
            </label>
            <input
              ref={keyInputRef}
              type="file"
              accept=".pem,.key"
              style={{ display: 'none' }}
              onChange={handleKeyFile}
            />
            <div
              style={{
                ...uploadZoneStyle,
                borderColor: keyPem ? 'var(--color-primary)' : undefined,
                color: keyPem ? 'var(--color-primary)' : undefined,
              }}
              onClick={() => keyInputRef.current?.click()}
            >
              {keyPem ? (
                <>
                  <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" style={{ verticalAlign: 'middle', marginRight: '0.375rem' }}>
                    <path d="M5 8l2 2 4-4" strokeLinecap="round" strokeLinejoin="round" />
                    <circle cx="8" cy="8" r="6" />
                  </svg>
                  {keyFileName}
                </>
              ) : (
                'Key-Datei auswaehlen'
              )}
            </div>
          </div>
        </div>
      </div>

      {/* Save Button */}
      <div style={{ display: 'flex', gap: '0.75rem', marginBottom: '2rem' }}>
        <button
          style={{
            ...btnPrimaryStyle,
            opacity: saveMutation.isPending ? 0.7 : 1,
            cursor: saveMutation.isPending ? 'wait' : 'pointer',
          }}
          onClick={handleSave}
          disabled={saveMutation.isPending || !dnsName.trim()}
        >
          {saveMutation.isPending
            ? 'Speichern...'
            : isActive
              ? 'Aktualisieren'
              : 'Speichern + Aktivieren'}
        </button>
      </div>

      {/* Info Box */}
      <div
        style={{
          padding: '1rem 1.25rem',
          background: 'var(--color-bg)',
          border: '1px solid var(--color-border)',
          borderRadius: 'var(--radius-sm)',
          fontSize: '0.8125rem',
          color: 'var(--color-text-muted)',
          lineHeight: 1.6,
        }}
      >
        <strong style={{ color: 'var(--color-text)' }}>Hinweise:</strong>
        <ul style={{ margin: '0.5rem 0 0', paddingLeft: '1.25rem' }}>
          <li>Das Zertifikat muss im PEM-Format vorliegen (Base64-kodiert, beginnt mit <code>-----BEGIN CERTIFICATE-----</code>).</li>
          <li>Der Private Key darf <strong>nicht</strong> passwortgeschuetzt sein.</li>
          <li>Nach dem Speichern wird Traefik automatisch neu geladen (kein Neustart noetig).</li>
          <li>Die bestehende IP-basierte Erreichbarkeit bleibt erhalten.</li>
          <li>
            <strong>CORS:</strong> Nach Aktivierung muessen die Umgebungsvariablen{' '}
            <code>CORS_ORIGINS</code>, <code>APP_URL</code> und <code>FRONTEND_URL</code>{' '}
            in der <code>.env</code> um die neue Domain ergaenzt werden.
          </li>
        </ul>
      </div>
    </div>
  );
}
