import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@/components/ui/sheet";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { ExternalLink, Download, FileText, Video, Music, Image, Link2 } from "lucide-react";
import { API_BASE_URL } from "@/lib/api-client";
import type { ChapterMaterial, MaterialType } from "@/types/courseware";

interface MaterialViewerProps {
  material: ChapterMaterial | null;
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onDownload?: (materialId: number, name: string) => void;
}

const typeLabels: Record<MaterialType, string> = {
  pdf: "PDF Document",
  document: "Document",
  video: "Video",
  audio: "Audio",
  image: "Image",
  link: "External Link",
  article: "Article",
};

const typeIcons: Record<MaterialType, React.ReactNode> = {
  pdf: <FileText className="h-4 w-4" />,
  document: <FileText className="h-4 w-4" />,
  video: <Video className="h-4 w-4" />,
  audio: <Music className="h-4 w-4" />,
  image: <Image className="h-4 w-4" />,
  link: <Link2 className="h-4 w-4" />,
  article: <FileText className="h-4 w-4" />,
};

function getContentUrl(materialId: number): string {
  const token = localStorage.getItem("encoach_token") ?? "";
  return `${API_BASE_URL}/materials/${materialId}/content?token=${token}`;
}

function isYouTubeUrl(url: string): boolean {
  return /(?:youtube\.com\/(?:watch|embed)|youtu\.be\/)/.test(url);
}

function getYouTubeEmbedUrl(url: string): string {
  const match = url.match(
    /(?:youtube\.com\/(?:watch\?v=|embed\/)|youtu\.be\/)([\w-]+)/
  );
  return match ? `https://www.youtube.com/embed/${match[1]}` : url;
}

function PdfViewer({ material }: { material: ChapterMaterial }) {
  if (material.file_url) {
    return (
      <iframe
        src={getContentUrl(material.id)}
        className="w-full h-full min-h-[600px] rounded-lg border"
        title={material.name}
      />
    );
  }
  if (material.url) {
    return (
      <iframe
        src={material.url}
        className="w-full h-full min-h-[600px] rounded-lg border"
        title={material.name}
      />
    );
  }
  return <EmptyState message="No PDF file available." />;
}

function VideoViewer({ material }: { material: ChapterMaterial }) {
  if (material.url && isYouTubeUrl(material.url)) {
    return (
      <iframe
        src={getYouTubeEmbedUrl(material.url)}
        className="w-full aspect-video rounded-lg border"
        title={material.name}
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
        allowFullScreen
      />
    );
  }
  if (material.url) {
    return (
      <video
        src={material.url}
        controls
        className="w-full rounded-lg border"
        title={material.name}
      >
        Your browser does not support the video tag.
      </video>
    );
  }
  if (material.file_url) {
    return (
      <video
        src={getContentUrl(material.id)}
        controls
        className="w-full rounded-lg border"
        title={material.name}
      >
        Your browser does not support the video tag.
      </video>
    );
  }
  return <EmptyState message="No video source available." />;
}

function AudioViewer({ material }: { material: ChapterMaterial }) {
  const src = material.url || (material.file_url ? getContentUrl(material.id) : null);
  if (!src) return <EmptyState message="No audio source available." />;
  return (
    <div className="flex items-center justify-center py-12">
      <audio src={src} controls className="w-full max-w-lg">
        Your browser does not support the audio element.
      </audio>
    </div>
  );
}

function ImageViewer({ material }: { material: ChapterMaterial }) {
  const src = material.url || (material.file_url ? getContentUrl(material.id) : null);
  if (!src) return <EmptyState message="No image available." />;
  return (
    <div className="flex items-center justify-center">
      <img
        src={src}
        alt={material.name}
        className="max-w-full max-h-[70vh] rounded-lg border object-contain"
      />
    </div>
  );
}

function ArticleViewer({ material }: { material: ChapterMaterial }) {
  if (!material.description) return <EmptyState message="No article content available." />;
  return (
    <div className="prose prose-sm dark:prose-invert max-w-none p-4 rounded-lg border bg-card">
      <div className="whitespace-pre-wrap">{material.description}</div>
    </div>
  );
}

function LinkViewer({ material }: { material: ChapterMaterial }) {
  if (!material.url) return <EmptyState message="No URL available." />;
  return (
    <div className="space-y-4">
      <div className="flex items-center gap-2 p-4 rounded-lg border bg-muted/50">
        <Link2 className="h-5 w-5 text-primary shrink-0" />
        <a
          href={material.url}
          target="_blank"
          rel="noopener noreferrer"
          className="text-primary underline break-all flex-1"
        >
          {material.url}
        </a>
        <Button variant="outline" size="sm" asChild>
          <a href={material.url} target="_blank" rel="noopener noreferrer">
            <ExternalLink className="h-4 w-4 mr-1" /> Open
          </a>
        </Button>
      </div>
      <iframe
        src={material.url}
        className="w-full min-h-[500px] rounded-lg border"
        title={material.name}
        sandbox="allow-scripts allow-same-origin"
      />
    </div>
  );
}

function EmptyState({ message }: { message: string }) {
  return (
    <div className="flex flex-col items-center justify-center py-16 text-muted-foreground">
      <FileText className="h-12 w-12 mb-3 opacity-40" />
      <p>{message}</p>
    </div>
  );
}

const viewers: Record<MaterialType, React.FC<{ material: ChapterMaterial }>> = {
  pdf: PdfViewer,
  document: PdfViewer,
  video: VideoViewer,
  audio: AudioViewer,
  image: ImageViewer,
  link: LinkViewer,
  article: ArticleViewer,
};

export default function MaterialViewer({ material, open, onOpenChange, onDownload }: MaterialViewerProps) {
  if (!material) return null;

  const Viewer = viewers[material.type] ?? ArticleViewer;

  return (
    <Sheet open={open} onOpenChange={onOpenChange}>
      <SheetContent side="right" className="w-full sm:max-w-2xl lg:max-w-4xl overflow-y-auto">
        <SheetHeader className="space-y-3 pb-4 border-b">
          <div className="flex items-center gap-2">
            {typeIcons[material.type]}
            <Badge variant="outline">{typeLabels[material.type]}</Badge>
          </div>
          <SheetTitle className="text-lg">{material.name}</SheetTitle>
          {material.description && material.type !== "article" && (
            <p className="text-sm text-muted-foreground">{material.description}</p>
          )}
          <div className="flex gap-2">
            {material.allow_download && material.file_url && onDownload && (
              <Button variant="outline" size="sm" onClick={() => onDownload(material.id, material.name)}>
                <Download className="h-4 w-4 mr-1" /> Download
              </Button>
            )}
            {material.url && (
              <Button variant="outline" size="sm" asChild>
                <a href={material.url} target="_blank" rel="noopener noreferrer">
                  <ExternalLink className="h-4 w-4 mr-1" /> Open Link
                </a>
              </Button>
            )}
          </div>
        </SheetHeader>

        <div className="mt-6">
          <Viewer material={material} />
        </div>
      </SheetContent>
    </Sheet>
  );
}
