import { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../../context/AuthContext';
import { auditLogApi, AuditLogSearchParams, authApi } from '../../services/api';
import type { AuditLog, AuditAction, AuditSensitivity } from '../../types';
import Card from '../../components/ui/Card';
import Button from '../../components/ui/Button';
import Input from '../../components/ui/Input';
import Select from '../../components/ui/Select';
import AuditIntegrityCard from './AuditIntegrityCard';
import { ArrowLeft, Download, Eye, Shield, ShieldAlert, RefreshCw, ChevronLeft, ChevronRight, X } from 'lucide-react';

const ACTION_OPTIONS = [
  { value: '', label: 'Alle Aktionen' },
  { value: 'CREATE', label: 'Erstellt' },
  { value: 'READ', label: 'Gelesen' },
  { value: 'UPDATE', label: 'Aktualisiert' },
  { value: 'DELETE', label: 'Gelöscht' },
  { value: 'EXPORT', label: 'Exportiert' },
  { value: 'ANONYMIZE', label: 'Anonymisiert' },
  { value: 'LOGIN', label: 'Login' },
  { value: 'LOGOUT', label: 'Logout' },
  { value: 'LOGIN_FAILED', label: 'Login fehlgeschlagen' },
  { value: 'TOKEN_REFRESH', label: 'Sitzung verlängert' },
];

const SENSITIVITY_OPTIONS = [
  { value: '', label: 'Alle Stufen' },
  { value: 'LOW', label: 'Niedrig' },
  { value: 'MEDIUM', label: 'Mittel' },
  { value: 'HIGH', label: 'Hoch' },
  { value: 'CRITICAL', label: 'Kritisch' },
];

const RESOURCE_OPTIONS = [
  { value: '', label: 'Alle Ressourcen' },
  { value: 'Customer', label: 'Kunden' },
  { value: 'Contract', label: 'Verträge' },
  { value: 'User', label: 'Benutzer' },
  { value: 'BankCard', label: 'Bankdaten' },
  { value: 'IdentityDocument', label: 'Ausweise' },
  { value: 'Address', label: 'Adressen' },
  { value: 'Meter', label: 'Zähler' },
  { value: 'ContractTask', label: 'Aufgaben' },
  { value: 'Authentication', label: 'Anmeldung' },
  { value: 'CustomerConsent', label: 'Einwilligungen' },
  { value: 'GDPR', label: 'DSGVO / Vollmacht' },
  { value: 'EmailProviderConfig', label: 'E-Mail-Provider' },
  { value: 'AppSetting', label: 'Einstellungen' },
];

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

function getActionColor(action: AuditAction): string {
  switch (action) {
    case 'CREATE': return 'bg-green-100 text-green-800';
    case 'READ': return 'bg-blue-100 text-blue-800';
    case 'UPDATE': return 'bg-yellow-100 text-yellow-800';
    case 'DELETE': return 'bg-red-100 text-red-800';
    case 'EXPORT': return 'bg-purple-100 text-purple-800';
    case 'ANONYMIZE': return 'bg-orange-100 text-orange-800';
    case 'LOGIN': return 'bg-teal-100 text-teal-800';
    case 'LOGOUT': return 'bg-gray-100 text-gray-800';
    case 'LOGIN_FAILED': return 'bg-red-200 text-red-900';
    case 'TOKEN_REFRESH': return 'bg-slate-50 text-slate-500';
    default: return 'bg-gray-100 text-gray-800';
  }
}

function getSensitivityIcon(sensitivity: AuditSensitivity) {
  switch (sensitivity) {
    case 'LOW': return <Shield className="w-4 h-4 text-gray-400" />;
    case 'MEDIUM': return <Shield className="w-4 h-4 text-blue-500" />;
    case 'HIGH': return <ShieldAlert className="w-4 h-4 text-orange-500" />;
    case 'CRITICAL': return <ShieldAlert className="w-4 h-4 text-red-500" />;
    default: return <Shield className="w-4 h-4 text-gray-400" />;
  }
}

const RESOURCE_TYPE_LABELS: Record<string, string> = {
  Customer: 'Kunde',
  Contract: 'Vertrag',
  BankCard: 'Bankverbindung',
  IdentityDocument: 'Ausweis',
  Address: 'Adresse',
  Meter: 'Zähler',
  MeterReading: 'Zählerstand',
  User: 'Benutzer',
  CustomerConsent: 'Einwilligung',
  RepresentativeAuthorization: 'Vollmacht',
  ContractTask: 'Aufgabe',
  EnergyContractDetails: 'Strom/Gas-Details',
  EmailProviderConfig: 'E-Mail-Provider',
  AppSetting: 'Einstellung',
  GDPR: 'Datenschutz',
  Authentication: 'Anmeldung',
};

const FIELD_LABELS: Record<string, string> = {
  firstName: 'Vorname', lastName: 'Nachname', email: 'E-Mail', phone: 'Telefon', mobile: 'Mobil',
  salutation: 'Anrede', companyName: 'Firma', type: 'Typ', notes: 'Notizen',
  street: 'Straße', houseNumber: 'Hausnummer', postalCode: 'PLZ', city: 'Stadt', country: 'Land',
  meterNumber: 'Zählernummer', location: 'Standort', tariffModel: 'Tarifmodell',
  isActive: 'Aktiv', isDefault: 'Standard',
  status: 'Status', source: 'Quelle',
  contractNumber: 'Vertragsnummer', startDate: 'Vertragsbeginn', endDate: 'Vertragsende',
  portalUsername: 'Portal-Benutzername', portalEnabled: 'Portal aktiv',
  basePrice: 'Grundpreis', unitPrice: 'Arbeitspreis', unitPriceNt: 'NT-Arbeitspreis', bonus: 'Bonus',
  name: 'Name', domain: 'Domain', apiUrl: 'API-URL',
  documentNumber: 'Dokumentennummer', expiryDate: 'Ablaufdatum',
  iban: 'IBAN', bic: 'BIC', bankName: 'Bank', accountHolder: 'Kontoinhaber',
  isGranted: 'Vollmacht erteilt', documentPath: 'Dokument-Pfad',
  value: 'Zählerstand', valueNt: 'NT-Zählerstand', readingDate: 'Ablesedatum',
  privacyPolicyPath: 'Datenschutz-PDF',
};

function formatValue(value: unknown): string {
  if (value === null || value === undefined) return '-';
  if (typeof value === 'boolean') return value ? 'Ja' : 'Nein';
  if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}/.test(value)) {
    try { return new Date(value).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' }); } catch { return value; }
  }
  return String(value);
}

function renderChangeDiff(before: Record<string, unknown>, after: Record<string, unknown>) {
  const allKeys = new Set([...Object.keys(before), ...Object.keys(after)]);
  const changes: { field: string; from: unknown; to: unknown }[] = [];

  for (const key of allKeys) {
    // Technische Felder überspringen
    if (['id', 'createdAt', 'updatedAt', 'passwordEncrypted', 'portalPasswordEncrypted', 'portalPasswordHash', 'systemEmailPasswordEncrypted'].includes(key)) continue;
    const fromVal = before[key];
    const toVal = after[key];
    if (JSON.stringify(fromVal) !== JSON.stringify(toVal)) {
      changes.push({ field: key, from: fromVal, to: toVal });
    }
  }

  if (changes.length === 0) {
    return <p className="text-sm text-gray-500 italic">Keine sichtbaren Änderungen</p>;
  }

  return changes.map(({ field, from, to }) => (
    <div key={field} className="flex items-start gap-3 p-2 bg-gray-50 rounded text-sm">
      <span className="font-medium text-gray-700 min-w-[150px]">
        {FIELD_LABELS[field] || field}
      </span>
      <span className="text-red-600 line-through">{formatValue(from)}</span>
      <span className="text-gray-400">→</span>
      <span className="text-green-700 font-medium">{formatValue(to)}</span>
    </div>
  ));
}

interface DetailModalProps {
  log: AuditLog;
  onClose: () => void;
}

function DetailModal({ log, onClose }: DetailModalProps) {
  const parseChanges = (changes: string | undefined): Record<string, unknown> | null => {
    if (!changes) return null;
    try {
      return JSON.parse(changes);
    } catch {
      return null;
    }
  };

  const before = parseChanges(log.changesBefore);
  const after = parseChanges(log.changesAfter);

  return (
    <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
      <div className="bg-white rounded-lg shadow-xl w-full max-w-3xl mx-4 max-h-[90vh] overflow-y-auto">
        <div className="p-6">
          <div className="flex items-center justify-between mb-4">
            <h2 className="text-xl font-semibold">Audit-Log Details</h2>
            <button onClick={onClose} className="text-gray-400 hover:text-gray-600">
              <X className="w-5 h-5" />
            </button>
          </div>

          <div className="grid grid-cols-2 gap-4 mb-6">
            <div>
              <dt className="text-sm text-gray-500">Zeitpunkt</dt>
              <dd className="font-medium">{formatDate(log.createdAt)}</dd>
            </div>
            <div>
              <dt className="text-sm text-gray-500">Benutzer</dt>
              <dd className="font-medium">{log.userEmail}</dd>
            </div>
            <div>
              <dt className="text-sm text-gray-500">Aktion</dt>
              <dd><span className={`px-2 py-1 rounded text-xs font-medium ${getActionColor(log.action)}`}>{log.action}</span></dd>
            </div>
            <div>
              <dt className="text-sm text-gray-500">Ressource</dt>
              <dd className="font-medium">{RESOURCE_TYPE_LABELS[log.resourceType] || log.resourceType} {log.resourceId && `#${log.resourceId}`}</dd>
            </div>
            <div>
              <dt className="text-sm text-gray-500">Endpoint</dt>
              <dd className="font-mono text-sm">{log.httpMethod} {log.endpoint}</dd>
            </div>
            <div>
              <dt className="text-sm text-gray-500">IP-Adresse</dt>
              <dd className="font-mono text-sm">{log.ipAddress}</dd>
            </div>
            <div>
              <dt className="text-sm text-gray-500">Sensitivität</dt>
              <dd className="flex items-center gap-2">{getSensitivityIcon(log.sensitivity)} {log.sensitivity}</dd>
            </div>
            <div>
              <dt className="text-sm text-gray-500">Dauer</dt>
              <dd>{log.durationMs ? `${log.durationMs}ms` : '-'}</dd>
            </div>
            {log.resourceLabel && (
              <div className="col-span-2">
                <dt className="text-sm text-gray-500">Ressource-Bezeichnung</dt>
                <dd className="font-medium">{log.resourceLabel}</dd>
              </div>
            )}
          </div>

          {log.changesEncrypted && (
            <div className="mb-4 p-3 bg-yellow-50 text-yellow-800 rounded-lg text-sm">
              Die Änderungsdaten sind verschlüsselt und können nur mit dem Encryption-Key eingesehen werden.
            </div>
          )}

          {(before || after) && !log.changesEncrypted && (
            <div className="border-t pt-4">
              <h3 className="font-medium mb-3">Änderungen</h3>
              {before && after ? (
                <div className="space-y-2">
                  {renderChangeDiff(before, after)}
                </div>
              ) : (
                <div className="grid grid-cols-2 gap-4">
                  {before && (
                    <div>
                      <h4 className="text-sm font-medium text-gray-500 mb-2">Vorher</h4>
                      <pre className="bg-gray-50 p-3 rounded text-xs overflow-auto max-h-64">
                        {JSON.stringify(before, null, 2)}
                      </pre>
                    </div>
                  )}
                  {after && (
                    <div>
                      <h4 className="text-sm font-medium text-gray-500 mb-2">Daten</h4>
                      <pre className="bg-gray-50 p-3 rounded text-xs overflow-auto max-h-64">
                        {JSON.stringify(after, null, 2)}
                      </pre>
                    </div>
                  )}
                </div>
              )}
            </div>
          )}


          <div className="flex justify-end mt-6 pt-4 border-t">
            <Button variant="secondary" onClick={onClose}>Schließen</Button>
          </div>
        </div>
      </div>
    </div>
  );
}

export default function AuditLogs() {
  const navigate = useNavigate();
  // Export haengt an `audit:export`, Lesen an `audit:read` – ein Konto darf
  // blaettern duerfen, ohne das gesamte Protokoll herausziehen zu koennen.
  // Ohne diese Abfrage stuenden hier Knoepfe, die zuverlaessig 403 liefern.
  const { hasPermission } = useAuth();
  const [page, setPage] = useState(1);
  const [filters, setFilters] = useState<AuditLogSearchParams>({
    page: 1,
    limit: 50,
  });
  const [selectedLog, setSelectedLog] = useState<AuditLog | null>(null);

  const { data: logsData, isLoading, refetch } = useQuery({
    queryKey: ['audit-logs', { ...filters, page }],
    queryFn: () => auditLogApi.search({ ...filters, page }),
  });


  const logs = logsData?.data || [];
  const pagination = logsData?.pagination;

  const handleFilterChange = (key: keyof AuditLogSearchParams, value: string) => {
    setFilters(prev => ({ ...prev, [key]: value || undefined }));
    setPage(1);
  };

  const handleExport = async (format: 'json' | 'csv') => {
    try {
      if (format === 'csv') {
        // CSV direkt als Download – mit kurzlebigem Download-Token (60s),
        // damit das langlebige Access-JWT nicht in Logs/Referer/History landet.
        const downloadToken = await authApi.getDownloadToken();
        const params = new URLSearchParams();
        params.set('format', 'csv');
        // ALLE aktiven Filter mitgeben (Pentest R186-01). Vorher standen hier
        // nur fuenf – wer im Suchfeld eingrenzte und dann CSV klickte, bekam
        // stillschweigend das gesamte Protokoll statt seiner Auswahl.
        // `page`/`limit` gehoeren nicht dazu: der Export ist bewusst
        // vollstaendig ueber die gefilterte Menge.
        for (const [schluessel, wert] of Object.entries(filters)) {
          if (schluessel === 'page' || schluessel === 'limit') continue;
          if (wert === undefined || wert === null || wert === '') continue;
          params.set(schluessel, String(wert));
        }
        window.open(`/api/audit-logs/export?${params}&token=${downloadToken ?? ''}`, '_blank');
      } else {
        const result = await auditLogApi.export({ ...filters, format });
        const blob = new Blob(
          [JSON.stringify(result.data, null, 2)],
          { type: 'application/json' }
        );
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `audit-logs-${new Date().toISOString().split('T')[0]}.json`;
        a.click();
        URL.revokeObjectURL(url);
      }
    } catch (error) {
      alert(`Export fehlgeschlagen: ${error instanceof Error ? error.message : 'Unbekannter Fehler'}`);
    }
  };

  return (
    <div>
      <div className="flex items-center gap-4 mb-6">
        <Button variant="ghost" onClick={() => navigate('/settings')}>
          <ArrowLeft className="w-4 h-4 mr-2" />
          Zurück
        </Button>
        <h1 className="text-2xl font-bold">Audit-Protokoll</h1>
      </div>

      <AuditIntegrityCard />

      {/* Filter */}
      <Card className="mb-6">
        <div className="grid grid-cols-1 md:grid-cols-4 gap-4 mb-4">
          <Input
            placeholder="Suche..."
            value={filters.search || ''}
            onChange={(e) => handleFilterChange('search', e.target.value)}
            className="w-full"
          />
          <Select
            value={filters.action || ''}
            onChange={(e) => handleFilterChange('action', e.target.value)}
            options={ACTION_OPTIONS}
          />
          <Select
            value={filters.resourceType || ''}
            onChange={(e) => handleFilterChange('resourceType', e.target.value)}
            options={RESOURCE_OPTIONS}
          />
          <Select
            value={filters.sensitivity || ''}
            onChange={(e) => handleFilterChange('sensitivity', e.target.value as AuditSensitivity)}
            options={SENSITIVITY_OPTIONS}
          />
        </div>
        <div className="grid grid-cols-1 md:grid-cols-4 gap-4 mb-4">
          <Input
            type="date"
            label="Von"
            value={filters.startDate || ''}
            onChange={(e) => handleFilterChange('startDate', e.target.value)}
          />
          <Input
            type="date"
            label="Bis"
            value={filters.endDate || ''}
            onChange={(e) => handleFilterChange('endDate', e.target.value)}
          />
          <div></div>
          <div className="flex gap-2 justify-end items-end">
            <Button variant="secondary" onClick={() => refetch()}>
              <RefreshCw className="w-4 h-4 mr-2" />
              Aktualisieren
            </Button>
            {hasPermission('audit:export') && (
              <Button variant="secondary" onClick={() => handleExport('json')}>
                <Download className="w-4 h-4 mr-2" />
                JSON
              </Button>
            )}
            {hasPermission('audit:export') && (
              <Button variant="secondary" onClick={() => handleExport('csv')}>
                <Download className="w-4 h-4 mr-2" />
                CSV
              </Button>
            )}
          </div>
        </div>
      </Card>

      {/* Tabelle */}
      <Card>
        {isLoading ? (
          <div className="text-center py-8">Laden...</div>
        ) : logs.length === 0 ? (
          <div className="text-center py-8 text-gray-500">Keine Audit-Logs gefunden.</div>
        ) : (
          <>
            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead>
                  <tr className="border-b">
                    <th className="text-left py-3 px-4">Zeitpunkt</th>
                    <th className="text-left py-3 px-4">Benutzer</th>
                    <th className="text-left py-3 px-4">Aktion</th>
                    <th className="text-left py-3 px-4">Ressource</th>
                    <th className="text-left py-3 px-4">IP</th>
                    <th className="text-center py-3 px-4"></th>
                    <th className="text-center py-3 px-4"></th>
                  </tr>
                </thead>
                <tbody>
                  {logs.map((log) => (
                    <tr key={log.id} className="border-b hover:bg-gray-50">
                      <td className="py-3 px-4 whitespace-nowrap">{formatDate(log.createdAt)}</td>
                      <td className="py-3 px-4">
                        <div className="truncate max-w-[200px]" title={log.userEmail}>
                          {log.userEmail}
                        </div>
                        {log.userRole && <div className="text-xs text-gray-500">{log.userRole}</div>}
                      </td>
                      <td className="py-3 px-4">
                        <span className={`px-2 py-1 rounded text-xs font-medium ${getActionColor(log.action)}`}>
                          {log.action}
                        </span>
                      </td>
                      <td className="py-3 px-4">
                        {log.resourceLabel ? (
                          <div className="text-sm truncate max-w-[300px]" title={log.resourceLabel}>
                            {log.resourceLabel}
                          </div>
                        ) : (
                          <div className="text-sm text-gray-500">{log.resourceType}</div>
                        )}
                      </td>
                      <td className="py-3 px-4 font-mono text-xs">{log.ipAddress}</td>
                      <td className="py-3 px-4 text-center">{getSensitivityIcon(log.sensitivity)}</td>
                      <td className="py-3 px-4 text-center">
                        <Button variant="ghost" size="sm" onClick={() => setSelectedLog(log)}>
                          <Eye className="w-4 h-4" />
                        </Button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>

            {/* Pagination */}
            {pagination && pagination.totalPages > 1 && (
              <div className="flex items-center justify-between mt-4 pt-4 border-t">
                <div className="text-sm text-gray-500">
                  Seite {pagination.page} von {pagination.totalPages} ({pagination.total} Einträge)
                </div>
                <div className="flex gap-2">
                  <Button
                    variant="secondary"
                    size="sm"
                    onClick={() => setPage(p => Math.max(1, p - 1))}
                    disabled={page === 1}
                  >
                    <ChevronLeft className="w-4 h-4" />
                  </Button>
                  <Button
                    variant="secondary"
                    size="sm"
                    onClick={() => setPage(p => Math.min(pagination.totalPages, p + 1))}
                    disabled={page === pagination.totalPages}
                  >
                    <ChevronRight className="w-4 h-4" />
                  </Button>
                </div>
              </div>
            )}
          </>
        )}
      </Card>

      {/* Detail Modal */}
      {selectedLog && (
        <DetailModal log={selectedLog} onClose={() => setSelectedLog(null)} />
      )}
    </div>
  );
}
