// components/ui/Feed.tsx
'use client';

import * as React from 'react';
import clsx from 'clsx';
import PersonAvatar from '@/components/ui/UserAvatar';

/* ───────── Types ───────── */

export type FeedPerson = {
  /**
   * Fallback-Anzeigename – z.B. E-Mail, wenn sonst nichts da ist.
   * In der Anzeige wird aber bevorzugt:
   * arbeitsname > "Vorname Nachname" > nwkennung > email > name
   */
  name: string;
  href?: string;
  imageUrl?: string; // optional: Avatar-Bild

  // Zusätzliche Infos, damit wir einen schönen Display-Namen bauen können
  arbeitsname?: string | null;
  firstName?: string | null;
  lastName?: string | null;
  nwkennung?: string | null;
  email?: string | null;
};

export type FeedTag = {
  name: string;
  href?: string;
  /** z.B. 'fill-red-500' */
  color?: string;
};

export type FeedChange = {
  field: string;
  /** Anzeigename, z.B. "Standort" statt "location" */
  label?: string;
  from: string | null;
  to: string | null;
};

export type FeedItem =
  | {
      id: string | number;
      type: 'comment';
      person: FeedPerson;
      imageUrl?: string;
      comment: string;
      /** Art des Kommentars – steuert nur noch Text, nicht mehr das Icon */
      commentKind?: 'created' | 'deleted' | 'generic' | 'loaned' | 'returned';
    }
  | {
      id: string | number;
      type: 'assignment';
      person: FeedPerson;
      assigned: FeedPerson;
      date: string;
    }
  | {
      id: string | number;
      type: 'tags';
      person: FeedPerson;
      tags: FeedTag[];
      date: string;
    }
  | {
      id: string | number;
      type: 'change';
      person: FeedPerson;
      changes: FeedChange[];
      date: string;
    };

export interface FeedProps {
  items: FeedItem[];
  className?: string;
}

/* ───────── Helper ───────── */

// DE Datum+Uhrzeit für Änderungen
const dtfDateTime = new Intl.DateTimeFormat('de-DE', {
  dateStyle: 'short',
  timeStyle: 'short',
});

/**
 * Erzeugt den eigentlichen Anzeigenamen für eine Person:
 * arbeitsname > "Vorname Nachname" > nwkennung > email > name
 */
function getDisplayName(person: FeedPerson): string {
  return (
    person.arbeitsname ??
    (person.firstName && person.lastName
      ? `${person.firstName} ${person.lastName}`
      : person.nwkennung ?? person.email ?? person.name)
  );
}

/** Werte für "change"-Einträge formatiert darstellen */
function formatChangeValue(field: string, value: string | null): string {
  if (!value) return '—';

  // Für Verleih-Daten: schön als Datum + Uhrzeit anzeigen
  if (field === 'loanedFrom' || field === 'loanedUntil') {
    const d = new Date(value);
    if (!isNaN(d.getTime())) {
      return dtfDateTime.format(d);
    }
  }

  // alles andere unverändert
  return value;
}

// sprechende Zusammenfassung für "change"
function getChangeSummary(
  item: Extract<FeedItem, { type: 'change' }>,
): React.ReactNode {
  const { changes } = item;
  if (!changes.length) return 'hat Änderungen vorgenommen';

  // Sonderfall: nur Tags
  if (changes.length === 1 && changes[0].field === 'tags') {
    const c = changes[0];
    const beforeList = (c.from ?? '')
      .split(',')
      .map((s) => s.trim())
      .filter(Boolean);
    const afterList = (c.to ?? '')
      .split(',')
      .map((s) => s.trim())
      .filter(Boolean);

    const beforeLower = beforeList.map((x) => x.toLowerCase());
    const afterLower = afterList.map((x) => x.toLowerCase());

    const added = afterList.filter(
      (t) => !beforeLower.includes(t.toLowerCase()),
    );
    const removed = beforeList.filter(
      (t) => !afterLower.includes(t.toLowerCase()),
    );

    const parts: string[] = [];
    if (added.length) parts.push(`hinzugefügt: ${added.join(', ')}`);
    if (removed.length) parts.push(`entfernt: ${removed.join(', ')}`);

    if (parts.length > 0) {
      return (
        <>
          hat Tags <em>{parts.join(' · ')}</em>
        </>
      );
    }
    return 'hat Tags angepasst';
  }

  if (changes.length === 1) {
    const c = changes[0];
    const label = c.label ?? c.field;
    return (
      <>
        hat <em>{label}</em> geändert
      </>
    );
  }

  const labels = changes.map((c) => c.label ?? c.field);
  const uniqueLabels = Array.from(new Set(labels));
  const maxShow = 3;

  if (uniqueLabels.length <= maxShow) {
    return (
      <>
        hat{' '}
        {uniqueLabels.map((label, index) => (
          <React.Fragment key={label}>
            <em>{label}</em>
            {index < uniqueLabels.length - 1 ? ', ' : ' '}
          </React.Fragment>
        ))}
        geändert
      </>
    );
  }

  const first = uniqueLabels.slice(0, maxShow);

  return (
    <>
      hat{' '}
      {first.map((label, index) => (
        <React.Fragment key={label}>
          <em>{label}</em>
          {index < first.length - 1 ? ', ' : ' '}
        </React.Fragment>
      ))}
      und weitere geändert
    </>
  );
}

function formatRelativeDate(raw: string): string {
  const d = new Date(raw);
  if (isNaN(d.getTime())) {
    // Falls kein gültiges Datum (z.B. schon formatiert), einfach roh anzeigen
    return raw;
  }

  const now = new Date();
  const diffMs = now.getTime() - d.getTime();
  const diffSec = Math.floor(diffMs / 1000);

  if (diffSec < 5) return 'gerade eben';
  if (diffSec < 60) return `vor ${diffSec} Sekunden`;

  const diffMin = Math.floor(diffSec / 60);
  if (diffMin < 60) {
    return `vor ${diffMin} Minute${diffMin === 1 ? '' : 'n'}`;
  }

  const diffH = Math.floor(diffMin / 60);
  if (diffH < 24) {
    return `vor ${diffH} Stunde${diffH === 1 ? '' : 'n'}`;
  }

  const diffD = Math.floor(diffH / 24);
  if (diffD < 30) {
    return `vor ${diffD} Tag${diffD === 1 ? '' : 'en'}`;
  }

  // Fallback: für ältere Einträge wieder absolutes Datum
  return new Intl.DateTimeFormat('de-DE', {
    dateStyle: 'short',
    timeStyle: 'short',
  }).format(d);
}

/* ───────── Component ───────── */

export default function Feed({ items, className }: FeedProps) {
  if (!items.length) {
    return (
      <p
        className={clsx(
          'text-sm text-gray-500 dark:text-gray-400',
          className,
        )}
      >
        Keine Aktivitäten vorhanden.
      </p>
    );
  }

  return (
    <ul role="list" className={clsx('pb-4', className)}>
      {items.map((item, idx) => {
        const actor = item.person;
        const actorDisplayName = getDisplayName(actor);

        // Textinhalt (content)
        let content: React.ReactNode = null;

        if (item.type === 'comment') {
          content = (
            <p className="text-xs text-gray-500 dark:text-gray-400">
              <span className="font-medium text-gray-900 dark:text-white">
                {actorDisplayName}
              </span>{' '}
              <span className="text-gray-300 dark:text-gray-200">
                {item.comment}
              </span>
            </p>
          );
        } else if (item.type === 'assignment') {
          const assignedDisplayName = getDisplayName(item.assigned);

          content = (
            <p className="text-xs text-gray-500 dark:text-gray-400">
              <span className="font-medium text-gray-900 dark:text-white">
                {actorDisplayName}
              </span>{' '}
              hat{' '}
              <span className="font-medium text-gray-900 dark:text-white">
                {assignedDisplayName}
              </span>{' '}
              zugewiesen.
            </p>
          );
        } else if (item.type === 'tags') {
          content = (
            <p className="text-xs text-gray-500 dark:text-gray-400">
              <span className="font-medium text-gray-900 dark:text-white">
                {actorDisplayName}
              </span>{' '}
              hat Tags hinzugefügt:{' '}
              <span className="font-medium text-gray-900 dark:text-gray-100">
                {item.tags.map((t) => t.name).join(', ')}
              </span>
            </p>
          );
        } else if (item.type === 'change') {
          const summary = getChangeSummary(item);
          content = (
            <div className="space-y-1">
              <p className="text-xs text-gray-500 dark:text-gray-400">
                <span className="font-medium text-gray-900 dark:text-white">
                  {actorDisplayName}
                </span>{' '}
                {summary}
              </p>
              {item.changes.length > 0 && (
                <p className="text-[11px] text-gray-400 dark:text-gray-500">
                  {item.changes.slice(0, 2).map((c, i) => (
                    <span
                      key={`${c.field}-${i}`}
                      className="flex flex-wrap items-baseline gap-x-1"
                    >
                      <span className="line-through text-red-500/80 dark:text-red-400/90">
                        {formatChangeValue(c.field, c.from)}
                      </span>
                      <span className="text-gray-400">→</span>
                      <span className="font-medium text-emerald-600 dark:text-emerald-400">
                        {formatChangeValue(c.field, c.to)}
                      </span>
                      {i < Math.min(2, item.changes.length) - 1 && (
                        <span className="mx-1 text-gray-500 dark:text-gray-600">
                          ·
                        </span>
                      )}
                    </span>
                  ))}
                  {item.changes.length > 2 && (
                    <span className="ml-1 text-gray-500 dark:text-gray-600">
                      · …
                    </span>
                  )}
                </p>
              )}
            </div>
          );
        }

        return (
          <li key={item.id}>
            <div className="relative pb-6">
              {idx !== items.length - 1 ? (
                <span
                  aria-hidden="true"
                  className="absolute top-4 left-4 -ml-px h-full w-0.5 bg-gray-200 dark:bg-white/10"
                />
              ) : null}

              <div className="relative flex space-x-3">
                {/* Avatar statt Icon-Badge */}
                <div className="mt-0.5">
                  <PersonAvatar
                    name={actorDisplayName}
                    avatarUrl={actor.imageUrl}
                    size="md"
                  />
                </div>

                <div className="flex min-w-0 flex-1 justify-between space-x-4 pt-1.5">
                  <div>{content}</div>
                  <div
                    className="whitespace-nowrap text-right text-[11px] text-gray-500 dark:text-gray-400"
                    title={item.date}
                  >
                    {formatRelativeDate(item.date)}
                  </div>
                </div>
              </div>
            </div>
          </li>
        );
      })}
    </ul>
  );
}
