"use client";

import { useEffect, useState, useRef, useCallback } from "react";
import { useActiveClass } from "@/hooks/use-active-class";
import { useAuth } from "@/hooks/use-auth";
import { fetchAPI, postAPI, putAPI, deleteAPI, uploadAPI, compressImage } from "@/lib/api";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { ConfirmDialog } from "@/components/confirm-dialog";
import { ErrorState } from "@/components/error-state";
import { Pagination } from "@/components/pagination";
import { toast } from "sonner";
import type { TimelinePost, TimelineComment } from "@/lib/types";

/* ---------- Relative time helper ---------- */
function relativeTime(dateStr: string): string {
  const now = Date.now();
  const then = new Date(dateStr).getTime();
  const diff = Math.floor((now - then) / 1000);
  if (diff < 60) return "刚刚";
  if (diff < 3600) return `${Math.floor(diff / 60)} 分钟前`;
  if (diff < 86400) return `${Math.floor(diff / 3600)} 小时前`;
  if (diff < 2592000) return `${Math.floor(diff / 86400)} 天前`;
  return new Date(dateStr).toLocaleDateString("zh-CN", {
    year: "numeric",
    month: "long",
    day: "numeric",
  });
}

/* ---------- Image Lightbox ---------- */
function Lightbox({
  images,
  initialIndex,
  onClose,
}: {
  images: string[];
  initialIndex: number;
  onClose: () => void;
}) {
  const [index, setIndex] = useState(initialIndex);

  const prev = useCallback(() => setIndex((i) => (i - 1 + images.length) % images.length), [images.length]);
  const next = useCallback(() => setIndex((i) => (i + 1) % images.length), [images.length]);

  // Keyboard & touch handling
  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") onClose();
      if (e.key === "ArrowLeft") prev();
      if (e.key === "ArrowRight") next();
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose, prev, next]);

  // Touch swipe
  const touchStartX = useRef(0);
  const handleTouchStart = (e: React.TouchEvent) => {
    touchStartX.current = e.touches[0].clientX;
  };
  const handleTouchEnd = (e: React.TouchEvent) => {
    const diff = e.changedTouches[0].clientX - touchStartX.current;
    if (Math.abs(diff) > 50) {
      diff > 0 ? prev() : next();
    }
  };

  return (
    <div
      className="fixed inset-0 z-50 bg-black/90 flex items-center justify-center"
      onClick={onClose}
    >
      {/* Close button */}
      <button
        className="absolute top-4 right-4 text-white/80 hover:text-white text-3xl z-10"
        onClick={onClose}
      >
        &times;
      </button>

      {/* Counter */}
      <div className="absolute top-4 left-4 text-white/70 text-sm">
        {index + 1} / {images.length}
      </div>

      {/* Prev arrow */}
      {images.length > 1 && (
        <button
          className="absolute left-4 top-1/2 -translate-y-1/2 w-10 h-10 rounded-full bg-white/10 hover:bg-white/20 text-white flex items-center justify-center text-xl z-10"
          onClick={(e) => { e.stopPropagation(); prev(); }}
        >
          &#8249;
        </button>
      )}

      {/* Image */}
      <img
        src={images[index]}
        alt=""
        className="max-w-[90vw] max-h-[85vh] object-contain select-none"
        onClick={(e) => e.stopPropagation()}
        onTouchStart={handleTouchStart}
        onTouchEnd={handleTouchEnd}
      />

      {/* Next arrow */}
      {images.length > 1 && (
        <button
          className="absolute right-4 top-1/2 -translate-y-1/2 w-10 h-10 rounded-full bg-white/10 hover:bg-white/20 text-white flex items-center justify-center text-xl z-10"
          onClick={(e) => { e.stopPropagation(); next(); }}
        >
          &#8250;
        </button>
      )}

      {/* Thumbnails */}
      {images.length > 1 && (
        <div
          className="absolute bottom-4 left-1/2 -translate-x-1/2 flex gap-2 z-10"
          onClick={(e) => e.stopPropagation()}
        >
          {images.map((url, i) => (
            <button
              key={i}
              className={`w-12 h-12 rounded overflow-hidden border-2 transition-opacity ${
                i === index ? "border-white opacity-100" : "border-transparent opacity-50 hover:opacity-75"
              }`}
              onClick={() => setIndex(i)}
            >
              <img src={url} alt="" className="w-full h-full object-cover" />
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

export default function TimelinePage() {
  const { activeClassId } = useActiveClass();
  const { user } = useAuth();
  const [posts, setPosts] = useState<TimelinePost[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [page, setPage] = useState(1);
  const [totalPages, setTotalPages] = useState(1);
  const [dialogOpen, setDialogOpen] = useState(false);
  const [newTitle, setNewTitle] = useState("");
  const [newContent, setNewContent] = useState("");
  const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
  const [previewUrls, setPreviewUrls] = useState<string[]>([]);
  const [submitting, setSubmitting] = useState(false);
  const [uploadProgress, setUploadProgress] = useState("");
  const [editingId, setEditingId] = useState<number | null>(null);
  const [editingImageUrls, setEditingImageUrls] = useState<string[]>([]);
  const fileInputRef = useRef<HTMLInputElement>(null);

  // Lightbox state
  const [lightboxImages, setLightboxImages] = useState<string[] | null>(null);
  const [lightboxIndex, setLightboxIndex] = useState(0);

  // Comment state
  const [expandedComments, setExpandedComments] = useState<Set<number>>(new Set());
  const [commentInputs, setCommentInputs] = useState<Record<number, string>>({});
  const [submittingComment, setSubmittingComment] = useState<Record<number, boolean>>({});

  const openLightbox = (images: string[], index: number) => {
    setLightboxImages(images);
    setLightboxIndex(index);
  };
  const closeLightbox = () => setLightboxImages(null);

  const loadPosts = async () => {
    setError(null);
    try {
      const res = await fetchAPI<any>("/api/timeline/", { page_size: "10", page: String(page), class_id: String(activeClassId) });
      setPosts(res.items || []);
      setTotalPages(res.total_pages || 1);
    } catch (err: any) {
      setError(err.message || "加载失败");
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    if (!activeClassId) return;
    loadPosts();
  }, [activeClassId, page]);

  /* ---------- File upload helpers ---------- */
  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = Array.from(e.target.files || []);
    // Max 9 images
    const toAdd = files.slice(0, 9 - selectedFiles.length - editingImageUrls.length);
    if (toAdd.length === 0) {
      toast.error("最多上传 9 张图片");
      return;
    }
    const newFiles = [...selectedFiles, ...toAdd];
    setSelectedFiles(newFiles);
    // Generate preview URLs
    const newUrls = toAdd.map((f) => URL.createObjectURL(f));
    setPreviewUrls((prev) => [...prev, ...newUrls]);
  };

  const removeFile = (index: number) => {
    URL.revokeObjectURL(previewUrls[index]);
    setSelectedFiles((prev) => prev.filter((_, i) => i !== index));
    setPreviewUrls((prev) => prev.filter((_, i) => i !== index));
  };

  const resetForm = () => {
    setEditingId(null);
    setEditingImageUrls([]);
    setNewTitle("");
    setNewContent("");
    previewUrls.forEach((url) => URL.revokeObjectURL(url));
    setSelectedFiles([]);
    setPreviewUrls([]);
    if (fileInputRef.current) fileInputRef.current.value = "";
  };

  const openEdit = (post: TimelinePost) => {
    setEditingId(post.id);
    setEditingImageUrls(post.image_urls || []);
    setNewTitle(post.title);
    setNewContent(post.content || "");
    setSelectedFiles([]);
    setPreviewUrls([]);
    setDialogOpen(true);
  };

  const handleCreate = async () => {
    if (!newTitle.trim()) return;
    setSubmitting(true);
    setUploadProgress("准备上传...");
    try {
      if (editingId) {
        // Edit mode: update text + upload new images separately
        await putAPI(`/api/timeline/${editingId}`, {
          title: newTitle,
          content: newContent || null,
        });
        if (selectedFiles.length > 0) {
          setUploadProgress(`压缩图片 (0/${selectedFiles.length})...`);
          const compressed = [];
          for (let i = 0; i < selectedFiles.length; i++) {
            compressed.push(await compressImage(selectedFiles[i]));
            setUploadProgress(`压缩图片 (${i + 1}/${selectedFiles.length})...`);
          }
          setUploadProgress("上传图片...");
          const formData = new FormData();
          for (const f of compressed) formData.append("files", f);
          await uploadAPI(`/api/timeline/${editingId}/images`, formData);
        }
        toast.success("已更新");
      } else {
        // Create mode: send everything in one FormData request
        const formData = new FormData();
        formData.append("title", newTitle);
        if (newContent) formData.append("content", newContent);
        if (user?.role === "super_admin" && activeClassId) formData.append("class_id", String(activeClassId));

        if (selectedFiles.length > 0) {
          setUploadProgress(`压缩图片 (0/${selectedFiles.length})...`);
          const compressed = [];
          for (let i = 0; i < selectedFiles.length; i++) {
            compressed.push(await compressImage(selectedFiles[i]));
            setUploadProgress(`压缩图片 (${i + 1}/${selectedFiles.length})...`);
          }
          setUploadProgress("上传中...");
          for (const f of compressed) formData.append("files", f);
        }

        await uploadAPI<TimelinePost>("/api/timeline/", formData);
        toast.success("发布成功");
      }

      resetForm();
      setDialogOpen(false);
      loadPosts();
    } catch (err: any) {
      toast.error(err.message || (editingId ? "更新失败" : "发布失败"));
    } finally {
      setSubmitting(false);
      setUploadProgress("");
    }
  };

  /* ---------- Delete post ---------- */
  const [deleteTarget, setDeleteTarget] = useState<number | null>(null);

  const handleDelete = async (id: number) => {
    try {
      await deleteAPI(`/api/timeline/${id}`);
      toast.success("已删除");
      setDeleteTarget(null);
      loadPosts();
    } catch (err: any) {
      toast.error(err.message || "删除失败");
    }
  };

  /* ---------- Like ---------- */
  const handleLike = async (postId: number) => {
    try {
      const res = await postAPI<{ liked: boolean; like_count: number }>(`/api/timeline/${postId}/like`);
      setPosts((prev) =>
        prev.map((p) =>
          p.id === postId
            ? { ...p, has_liked: res.liked, like_count: res.like_count }
            : p
        )
      );
    } catch (err: any) {
      toast.error(err.message || "操作失败");
    }
  };

  /* ---------- Comments ---------- */
  const toggleComments = async (postId: number) => {
    setExpandedComments((prev) => {
      const next = new Set(prev);
      if (next.has(postId)) {
        next.delete(postId);
        return next;
      }
      next.add(postId);
      return next;
    });

    // Fetch comments when expanding (if not already loaded)
    if (!expandedComments.has(postId)) {
      try {
        const res = await fetchAPI<any>(`/api/timeline/${postId}/comments`);
        const comments = res.items || [];
        setPosts((prev) =>
          prev.map((p) =>
            p.id === postId ? { ...p, comments } : p
          )
        );
      } catch {
        // Silently fail — user can still try to post a new comment
      }
    }
  };

  const handleAddComment = async (postId: number) => {
    const content = (commentInputs[postId] || "").trim();
    if (!content) return;
    setSubmittingComment((prev) => ({ ...prev, [postId]: true }));
    try {
      const newComment = await postAPI<TimelineComment>(`/api/timeline/${postId}/comments`, { content });
      setPosts((prev) =>
        prev.map((p) => {
          if (p.id !== postId) return p;
          const comments = [...(p.comments || []), newComment];
          return { ...p, comments, comment_count: comments.length };
        })
      );
      setCommentInputs((prev) => ({ ...prev, [postId]: "" }));
    } catch (err: any) {
      toast.error(err.message || "评论失败");
    } finally {
      setSubmittingComment((prev) => ({ ...prev, [postId]: false }));
    }
  };

  const handleDeleteComment = async (postId: number, commentId: number) => {
    try {
      await deleteAPI(`/api/timeline/comments/${commentId}`);
      setPosts((prev) =>
        prev.map((p) => {
          if (p.id !== postId) return p;
          const comments = (p.comments || []).filter((c) => c.id !== commentId);
          return { ...p, comments, comment_count: comments.length };
        })
      );
      toast.success("已删除评论");
    } catch (err: any) {
      toast.error(err.message || "删除评论失败");
    }
  };

  /* ---------- Permission helpers ---------- */
  const canEditDelete = (post: TimelinePost): boolean => {
    if (!user) return false;
    if (user.role === "class_admin" || user.role === "super_admin") return true;
    return user.id === post.author_id;
  };

  const canDeleteComment = (comment: TimelineComment): boolean => {
    if (!user) return false;
    if (user.role === "class_admin" || user.role === "super_admin") return true;
    return user.id === comment.author_id;
  };

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-bold">班级动态</h1>
          <p className="text-gray-500 mt-1">分享动态，交流互动</p>
        </div>
        <Dialog open={dialogOpen} onOpenChange={(open) => {
          setDialogOpen(open);
          if (!open) resetForm();
        }}>
          <DialogTrigger>
            <Button>发布动态</Button>
          </DialogTrigger>
          <DialogContent>
            <DialogHeader>
              <DialogTitle>{editingId ? "编辑动态" : "发布动态"}</DialogTitle>
            </DialogHeader>
            <div className="space-y-4 pt-2">
              <Input
                placeholder="标题"
                value={newTitle}
                onChange={(e) => setNewTitle(e.target.value)}
              />
              <Textarea
                placeholder="内容描述..."
                value={newContent}
                onChange={(e) => setNewContent(e.target.value)}
                rows={4}
              />
              {/* Image upload */}
              <div>
                <input
                  ref={fileInputRef}
                  type="file"
                  accept="image/jpeg,image/png,image/gif,image/webp"
                  multiple
                  className="hidden"
                  onChange={handleFileChange}
                />
                <div className="flex flex-wrap gap-2">
                  {/* Existing images (edit mode) */}
                  {editingImageUrls.map((url, idx) => (
                    <div key={`existing-${idx}`} className="relative w-20 h-20 rounded-lg overflow-hidden border">
                      <img src={url} alt="" className="w-full h-full object-cover" />
                    </div>
                  ))}
                  {/* New image previews */}
                  {previewUrls.map((url, idx) => (
                    <div key={idx} className="relative w-20 h-20 rounded-lg overflow-hidden border">
                      <img src={url} alt="" className="w-full h-full object-cover" />
                      <button
                        type="button"
                        className="absolute top-0 right-0 w-5 h-5 bg-black/60 text-white text-xs flex items-center justify-center rounded-bl"
                        onClick={() => removeFile(idx)}
                      >
                        x
                      </button>
                    </div>
                  ))}
                  {(selectedFiles.length + editingImageUrls.length) < 9 && (
                    <button
                      type="button"
                      className="w-20 h-20 border-2 border-dashed border-gray-300 rounded-lg flex items-center justify-center text-gray-400 hover:border-gray-400 hover:text-gray-500 transition-colors"
                      onClick={() => fileInputRef.current?.click()}
                    >
                      <span className="text-2xl">+</span>
                    </button>
                  )}
                </div>
                <p className="text-xs text-gray-400 mt-1">最多 9 张，支持 JPG/PNG/GIF/WebP</p>
              </div>
              <Button onClick={handleCreate} disabled={submitting} className="w-full">
                {submitting ? (uploadProgress || (editingId ? "保存中..." : "发布中...")) : (editingId ? "保存" : "发布")}
              </Button>
            </div>
          </DialogContent>
        </Dialog>
      </div>

      {loading ? (
        <div className="space-y-4">
          {[1, 2, 3].map((i) => (
            <Card key={i} className="animate-pulse">
              <CardContent className="p-6">
                <div className="h-40 bg-gray-200 rounded" />
              </CardContent>
            </Card>
          ))}
        </div>
      ) : error ? (
        <ErrorState message={error} onRetry={loadPosts} />
      ) : posts.length === 0 ? (
        <div className="text-center py-12 text-gray-400">暂无动态，快来发布第一条吧</div>
      ) : (
        <div className="space-y-6">
          {posts.map((post) => (
            <Card key={post.id}>
              <CardContent className="p-6">
                <div className="flex items-start justify-between">
                  <div>
                    <h3 className="text-lg font-semibold">{post.title}</h3>
                    <p className="text-sm text-gray-500 mt-1">
                      {post.author_name} ·{" "}
                      {new Date(post.created_at).toLocaleDateString("zh-CN", {
                        year: "numeric",
                        month: "long",
                        day: "numeric",
                      })}
                    </p>
                  </div>
                  {canEditDelete(post) && (
                    <div className="flex gap-1">
                      <Button
                        variant="ghost"
                        size="sm"
                        onClick={() => openEdit(post)}
                      >
                        编辑
                      </Button>
                      <Button
                        variant="ghost"
                        size="sm"
                        className="text-red-500 hover:text-red-700"
                        onClick={() => setDeleteTarget(post.id)}
                      >
                        删除
                      </Button>
                    </div>
                  )}
                </div>
                {post.content && (
                  <p className="mt-4 text-gray-700 whitespace-pre-wrap">
                    {post.content}
                  </p>
                )}
                {post.image_urls && post.image_urls.length > 0 && (
                  <div className="mt-4 grid grid-cols-2 md:grid-cols-3 gap-2">
                    {post.image_urls.map((url, idx) => (
                      <div
                        key={idx}
                        className="aspect-video bg-gray-100 rounded-lg overflow-hidden cursor-pointer hover:opacity-90 transition-opacity"
                        onClick={() => openLightbox(post.image_urls!, idx)}
                      >
                        <img
                          src={url}
                          alt=""
                          className="w-full h-full object-cover"
                        />
                      </div>
                    ))}
                  </div>
                )}

                {/* Action bar */}
                <div className="mt-4 pt-3 border-t flex items-center gap-6 text-sm">
                  {/* Like button */}
                  <button
                    className="flex items-center gap-1.5 transition-colors hover:text-red-500"
                    onClick={() => handleLike(post.id)}
                  >
                    {post.has_liked ? (
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        viewBox="0 0 24 24"
                        fill="currentColor"
                        className="w-5 h-5 text-red-500"
                      >
                        <path d="m11.645 20.91-.007-.003-.022-.012a15.247 15.247 0 0 1-.383-.218 25.18 25.18 0 0 1-4.244-3.17C4.688 15.36 2.25 12.174 2.25 8.25 2.25 5.322 4.714 3 7.688 3A5.5 5.5 0 0 1 12 5.052 5.5 5.5 0 0 1 16.313 3c2.973 0 5.437 2.322 5.437 5.25 0 3.925-2.438 7.111-4.739 9.256a25.175 25.175 0 0 1-4.244 3.17 15.247 15.247 0 0 1-.383.219l-.022.012-.007.004-.003.001a.752.752 0 0 1-.704 0l-.003-.001Z" />
                      </svg>
                    ) : (
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        fill="none"
                        viewBox="0 0 24 24"
                        strokeWidth={1.5}
                        stroke="currentColor"
                        className="w-5 h-5"
                      >
                        <path strokeLinecap="round" strokeLinejoin="round" d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" />
                      </svg>
                    )}
                    <span className={post.has_liked ? "text-red-500 font-medium" : "text-gray-500"}>
                      {post.like_count > 0 ? post.like_count : "赞"}
                    </span>
                  </button>

                  {/* Comment button */}
                  <button
                    className="flex items-center gap-1.5 transition-colors hover:text-blue-500"
                    onClick={() => toggleComments(post.id)}
                  >
                    <svg
                      xmlns="http://www.w3.org/2000/svg"
                      fill="none"
                      viewBox="0 0 24 24"
                      strokeWidth={1.5}
                      stroke="currentColor"
                      className="w-5 h-5"
                    >
                      <path strokeLinecap="round" strokeLinejoin="round" d="M12 20.25c4.97 0 9-3.694 9-8.25s-4.03-8.25-9-8.25S3 7.444 3 12c0 2.104.859 4.023 2.273 5.48.432.447.74 1.04.586 1.641a4.483 4.483 0 0 1-.923 1.785A5.969 5.969 0 0 0 6 21c1.282 0 2.47-.402 3.445-1.087.81.22 1.668.337 2.555.337Z" />
                    </svg>
                    <span className="text-gray-500">
                      {post.comment_count > 0 ? post.comment_count : "评论"}
                    </span>
                  </button>
                </div>

                {/* Comment section (expandable) */}
                {expandedComments.has(post.id) && (
                  <div className="mt-3 pt-3 border-t">
                    {/* Existing comments */}
                    {post.comments && post.comments.length > 0 && (
                      <div className="space-y-3 mb-3">
                        {post.comments.map((comment) => (
                          <div key={comment.id} className="flex items-start gap-2 group">
                            <div className="flex-1 min-w-0">
                              <div className="flex items-center gap-2">
                                <span className="text-sm font-medium text-gray-800">{comment.author_name}</span>
                                <span className="text-xs text-gray-400">{relativeTime(comment.created_at)}</span>
                              </div>
                              <p className="text-sm text-gray-600 mt-0.5">{comment.content}</p>
                            </div>
                            {canDeleteComment(comment) && (
                              <button
                                className="opacity-0 group-hover:opacity-100 transition-opacity text-gray-400 hover:text-red-500 p-1 shrink-0"
                                title="删除评论"
                                onClick={() => handleDeleteComment(post.id, comment.id)}
                              >
                                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-4 h-4">
                                  <path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12" />
                                </svg>
                              </button>
                            )}
                          </div>
                        ))}
                      </div>
                    )}

                    {/* New comment input */}
                    <div className="flex gap-2">
                      <Input
                        placeholder="写评论..."
                        value={commentInputs[post.id] || ""}
                        onChange={(e) =>
                          setCommentInputs((prev) => ({ ...prev, [post.id]: e.target.value }))
                        }
                        onKeyDown={(e) => {
                          if (e.key === "Enter" && !e.shiftKey) {
                            e.preventDefault();
                            handleAddComment(post.id);
                          }
                        }}
                        disabled={submittingComment[post.id]}
                        className="flex-1"
                      />
                      <Button
                        size="sm"
                        onClick={() => handleAddComment(post.id)}
                        disabled={submittingComment[post.id] || !(commentInputs[post.id] || "").trim()}
                      >
                        发送
                      </Button>
                    </div>
                  </div>
                )}
              </CardContent>
            </Card>
          ))}
        </div>
      )}

      <Pagination page={page} totalPages={totalPages} onPageChange={setPage} />

      {/* Delete confirmation */}
      <ConfirmDialog
        open={deleteTarget !== null}
        onOpenChange={(open) => { if (!open) setDeleteTarget(null); }}
        title="删除动态"
        description="确定删除这条动态？此操作不可恢复。"
        confirmText="删除"
        variant="destructive"
        onConfirm={() => deleteTarget && handleDelete(deleteTarget)}
      />

      {/* Lightbox */}
      {lightboxImages && (
        <Lightbox
          images={lightboxImages}
          initialIndex={lightboxIndex}
          onClose={closeLightbox}
        />
      )}
    </div>
  );
}
