import { useMemo } from "react";
import { useNavigate } from "react-router-dom";
import {
  Radio,
  MessageSquare,
  Video,
  Mic,
  Image,
  FileText,
  CircleCheck,
  StickyNote,
  type LucideIcon,
} from "lucide-react";
import { cn } from "@/lib/utils";
import { useLiveParticleChildren, useLiveLatestChild } from "@/hooks/use-particle";
import { useAuthStore } from "@/stores/auth-store";
import {
  parseParticlePath,
  particlePath,
  type ParticlePath,
} from "@/lib/particle-path";
import { getInitials } from "@/lib/utils";
import { formatDistanceToNow } from "@/lib/time-utils";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Separator } from "@/components/ui/separator";
import { Progress } from "@/components/ui/progress";
import { Small } from "@/components/ui/typography";
import type { Particle, StreamProperties } from "@/api/types";

function getParticleTypeIcon(particle: Particle): LucideIcon {
  switch (particle.type) {
    case "text":
      return MessageSquare;
    case "media": {
      const mime = particle.properties.mime_type;
      if (mime.startsWith("video/")) return Video;
      if (mime.startsWith("audio/")) return Mic;
      if (mime.startsWith("image/")) return Image;
      return Video;
    }
    case "file":
      return FileText;
    case "quest":
      return CircleCheck;
    case "paper":
      return StickyNote;
    default:
      return Radio;
  }
}

function getMessagePreview(particle: Particle): string {
  switch (particle.type) {
    case "text":
      return particle.properties.content;
    case "media": {
      const mime = particle.properties.mime_type;
      if (mime.startsWith("video/")) return "Video clip";
      if (mime.startsWith("audio/")) return "Voice note";
      if (mime.startsWith("image/")) return "Photo";
      return "Media";
    }
    case "file":
      return particle.properties.filename;
    case "quest":
      return particle.properties.title;
    case "paper":
      return particle.properties.title;
    default:
      return particle.type;
  }
}

function StreamRow({
  particle,
  networkId,
  onClick,
}: {
  particle: Particle & { type: "stream"; properties: StreamProperties };
  networkId: string;
  onClick: () => void;
}) {
  const streamPath = particlePath(networkId, [particle.id]);
  const { latestChild } = useLiveLatestChild(streamPath);
  const user = useAuthStore((s) => s.user);
  const userId = user?.id ?? "";
  const userEmail = user?.email ?? "";

  const isDM =
    particle.visible_to.length === 2 &&
    particle.visible_to.every((v) => v.startsWith("human:"));

  const initials = useMemo(() => {
    if (isDM) {
      const otherEntry = particle.visible_to.find(
        (v) => v !== `human:${userEmail}`,
      );
      if (otherEntry) {
        const otherEmail = otherEntry.replace("human:", "");
        return getInitials(otherEmail);
      }
    }
    return particle.properties.name.slice(0, 2).toUpperCase();
  }, [isDM, particle.visible_to, particle.properties.name, userEmail]);

  const isUnseen = useMemo(() => {
    if (!latestChild) return false;
    const latestChildTimestamp = latestChild.created_at.getTime();
    const userPlaybackPosition =
      particle.playback_markers?.[userId]?.getTime() ?? 0;
    return latestChildTimestamp > userPlaybackPosition;
  }, [latestChild, particle.playback_markers, userId]);

  const senderPrefix = useMemo(() => {
    if (!latestChild) return null;
    const isCurrentUser = latestChild.created_by_email === userEmail;
    if (isDM) {
      return isCurrentUser ? "You: " : null;
    }
    // Group stream
    if (isCurrentUser) return "You: ";
    const emailPrefix = latestChild.created_by_email.split("@")[0];
    const capitalized =
      emailPrefix.charAt(0).toUpperCase() + emailPrefix.slice(1);
    return `${capitalized}: `;
  }, [latestChild, userEmail, isDM]);

  const subtitle = latestChild
    ? getMessagePreview(latestChild)
    : particle.properties.status;

  const TypeIcon = latestChild ? getParticleTypeIcon(latestChild) : Radio;

  return (
    <button
      type="button"
      onClick={onClick}
      className="flex w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-accent"
    >
      <Avatar
        className={cn(isUnseen && "ring-2 ring-primary")}
      >
        <AvatarFallback className="bg-primary/10 text-primary font-medium">
          {initials}
        </AvatarFallback>
      </Avatar>
      <div className="min-w-0 flex-1">
        <div className="flex items-center justify-between gap-2">
          <p
            className={cn(
              "truncate text-sm",
              isUnseen
                ? "font-semibold text-foreground"
                : "font-medium text-muted-foreground",
            )}
          >
            {particle.properties.name}
          </p>
          {latestChild && (
            <Small
              className={cn(
                "shrink-0",
                isUnseen ? "text-primary" : "text-muted-foreground",
              )}
            >
              {formatDistanceToNow(latestChild.created_at.toISOString())}
            </Small>
          )}
        </div>
        <div className="flex items-center gap-1">
          <TypeIcon
            className={cn(
              "size-3.5 shrink-0",
              isUnseen ? "text-foreground" : "text-muted-foreground",
            )}
          />
          <Small
            className={cn(
              "truncate",
              isUnseen
                ? "text-foreground font-medium"
                : "text-muted-foreground font-normal",
            )}
          >
            {senderPrefix && (
              <span className="text-muted-foreground">{senderPrefix}</span>
            )}
            {subtitle}
          </Small>
        </div>
      </div>
      {isUnseen && (
        <span className="size-2 shrink-0 rounded-full bg-primary" />
      )}
    </button>
  );
}

interface ParticleListViewProps {
  path: ParticlePath;
}

/**
 * List of stream particles for a container (network root, folder, etc.).
 */
export function ParticleListView({ path }: ParticleListViewProps) {
  const { children, isLoading } = useLiveParticleChildren(path, "last_child_created_at", "desc");
  const { networkId } = parseParticlePath(path);
  const navigate = useNavigate();

  const streams = useMemo(
    () => children.filter((c) => c.type === "stream"),
    [children],
  );

  if (isLoading) {
    return <Progress />;
  }

  return (
    <ScrollArea className="h-full">
      <div className="py-1">
        {streams.map((stream, index) => (
          <div key={stream.id}>
            <StreamRow
              particle={stream}
              networkId={networkId}
              onClick={() => navigate(`/${networkId}/${stream.id}`)}
            />
            {index < streams.length - 1 && <Separator className="mx-4" />}
          </div>
        ))}
      </div>
    </ScrollArea>
  );
}
