"use client";

import Image from "next/image";
import Link from "next/link";
import { useEffect, useRef, useState, useCallback } from "react";
import { useRouter } from "next/navigation";
import { useAppDispatch, useAppSelector } from "@/store/hooks";
import {
  fetchFeed,
  deleteFeed,
  uploadFeed,
  uploadFeedContent,
  selectFeedItems,
  selectFeedsLoading,
  selectFeedsHasMore,
  selectFeedsPage,
  selectFeedsPosting,
} from "@/store/slices/feedsSlice";
import { getStoredUser } from "@/lib/utils/persistAuth";
import { useToast } from "@/lib/toast";
import CommentDrawer from "@/features/common/components/CommentDrawer";
import ReportModal from "@/features/common/components/ReportModal";
import type { FeedItem, FeedContentItem } from "@/types/api/feeds.types";

// ── Helpers ───────────────────────────────────────────────────────────────────
function isValidImg(url?: string) {
  return !!url && !url.includes("no_img");
}
function fmtRelTime(d: string) {
  const diff = Date.now() - new Date(d).getTime();
  const m = Math.floor(diff / 60_000);
  const h = Math.floor(m / 60);
  if (m < 1) return "just now";
  if (m < 60) return `${m}m`;
  if (h < 24) return `${h}h`;
  return `${Math.floor(h / 24)}d`;
}

async function callLikeUnlike(contentId: number, userId: number): Promise<string> {
  const { default: apiClient } = await import("@/services/api.client");
  const { API_ENDPOINTS } = await import("@/lib/constants/apiEndpoints");
  const { data } = await apiClient.post<{ status: number; message: string; result: unknown[] }>(
    API_ENDPOINTS.LIKE_UNLIKE,
    { user_id: userId, type: 6, content_id: contentId, video_id: 0 },
  );
  return data.message ?? "";
}

// ── Media Grid ────────────────────────────────────────────────────────────────
function MediaGrid({ items }: { items: FeedContentItem[] }) {
  if (!items.length) return null;
  const count = Math.min(items.length, 4);

  const cellStyle = (idx: number): React.CSSProperties => ({
    position: "relative",
    borderRadius: count === 1 ? 10 : 0,
    overflow: "hidden",
    background: "#0f172a",
    gridColumn: count === 3 && idx === 0 ? "1 / span 2" : undefined,
    minHeight: count === 1 ? 220 : count === 3 && idx === 0 ? 180 : 130,
  });

  const gridTemplate =
    count === 1 ? "1fr" :
    count === 2 ? "1fr 1fr" :
    count === 3 ? "1fr 1fr" :
    "1fr 1fr";

  return (
    <div style={{
      display: "grid",
      gridTemplateColumns: gridTemplate,
      gap: 2,
      borderRadius: 10,
      overflow: "hidden",
      marginTop: "0.75rem",
    }}>
      {items.slice(0, 4).map((item, idx) => (
        <div key={item.id} style={cellStyle(idx)}>
          {item.content_type === 2 && item.video ? (
            /* Video */
            <video
              src={item.video}
              controls
              playsInline
              style={{ width: "100%", height: "100%", objectFit: "cover", display: "block" }}
            />
          ) : isValidImg(item.image) ? (
            /* Real image */
            <Image src={item.image} alt="" fill style={{ objectFit: "cover" }} unoptimized />
          ) : item.content_type === 2 ? (
            /* Video placeholder */
            <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", flexDirection: "column", gap: 8 }}>
              <div style={{ width: 40, height: 40, borderRadius: "50%", background: "rgba(255,255,255,0.12)", display: "flex", alignItems: "center", justifyContent: "center" }}>
                <svg width="18" height="18" viewBox="0 0 24 24" fill="rgba(255,255,255,0.8)"><polygon points="6 4 20 12 6 20" /></svg>
              </div>
              <span style={{ fontSize: 11, color: "rgba(255,255,255,0.4)", fontFamily: "var(--mono)" }}>Video</span>
            </div>
          ) : (
            /* Image placeholder with gradient */
            <div style={{ position: "absolute", inset: 0, background: `linear-gradient(135deg, #1e293b 0%, #0f172a 100%)`, display: "flex", alignItems: "center", justifyContent: "center", flexDirection: "column", gap: 6 }}>
              <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="rgba(255,255,255,0.2)" strokeWidth="1.5">
                <rect x="3" y="3" width="18" height="18" rx="2" />
                <circle cx="8.5" cy="8.5" r="1.5" />
                <path d="M21 15l-5-5L5 21" />
              </svg>
              <span style={{ fontSize: 10, color: "rgba(255,255,255,0.2)", fontFamily: "var(--mono)", letterSpacing: "0.05em" }}>Photo</span>
            </div>
          )}
          {/* +N overlay for 4th cell */}
          {idx === 3 && items.length > 4 && (
            <div style={{ position: "absolute", inset: 0, background: "rgba(0,0,0,0.6)", display: "flex", alignItems: "center", justifyContent: "center" }}>
              <span style={{ color: "#fff", fontWeight: 800, fontSize: "1.375rem" }}>+{items.length - 4}</span>
            </div>
          )}
        </div>
      ))}
    </div>
  );
}

// ── Feed Card ─────────────────────────────────────────────────────────────────
function FeedCard({ feed, userId }: { feed: FeedItem; userId: number }) {
  const dispatch = useAppDispatch();
  const { success, error: showError } = useToast();
  const [menuOpen, setMenuOpen] = useState(false);
  const [liked, setLiked] = useState(feed.is_user_like === 1);
  const [likeCount, setLikeCount] = useState(feed.total_like);
  const [commentOpen, setCommentOpen] = useState(false);
  const [reportOpen, setReportOpen] = useState(false);

  const isChannel = feed.type === 2;
  const isOwn = !isChannel && feed.user_id === userId;
  const authorName  = isChannel ? (feed.channel_name ?? "Channel") : (feed.user_name ?? "User");
  const authorImg   = isChannel ? feed.channel_image : feed.user_image;

  async function handleLike() {
    if (!userId) { showError("Sign in to like"); const r = typeof window !== 'undefined' && window.location; window.location.href = '/login'; return; }
    const next = !liked;
    setLiked(next);
    setLikeCount((c) => c + (next ? 1 : -1));
    try {
      const msg = await callLikeUnlike(feed.id, userId);
      success(msg || (next ? "Like Added" : "Unliked Content"));
    } catch {
      setLiked(!next);
      setLikeCount((c) => c + (!next ? 1 : -1));
      showError("Failed to update like");
    }
  }

  async function handleDelete() {
    const res = await dispatch(deleteFeed({ feedId: feed.id }));
    if (deleteFeed.fulfilled.match(res)) {
      success("Post deleted");
    } else {
      showError("Failed to delete post");
    }
    setMenuOpen(false);
  }

  return (
    <>
      <article style={{
        background: "var(--surface)",
        border: "1px solid var(--border)",
        borderRadius: 12,
        padding: "1rem 1.125rem",
        marginBottom: "0.75rem",
      }}>
        {/* ── Header ── */}
        <div style={{ display: "flex", alignItems: "flex-start", gap: "0.75rem", marginBottom: "0.625rem" }}>
          {/* Author avatar + name — clickable */}
          {(() => {
            const authorHref = isChannel
              ? `/channel/${feed.channel_id}`
              : isOwn
              ? `/profile`
              : `/user/${feed.user_id}`;

            const avatarAndName = (
              <>
                <div style={{ flexShrink: 0, width: 38, height: 38, borderRadius: "50%", overflow: "hidden", background: "var(--brand-08, rgba(193,39,45,0.08))", display: "flex", alignItems: "center", justifyContent: "center", position: "relative" }}>
                  {isValidImg(authorImg)
                    ? <Image src={authorImg!} alt="" fill style={{ objectFit: "cover" }} unoptimized />
                    : <span style={{ fontSize: 14, fontWeight: 800, color: "var(--brand, #C1272D)" }}>{authorName.charAt(0).toUpperCase()}</span>
                  }
                </div>

                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ display: "flex", alignItems: "center", gap: "0.375rem", flexWrap: "wrap" }}>
                    <span style={{ fontWeight: 700, fontSize: "0.875rem", color: "var(--ink, #0e0e11)" }}>{authorName}</span>
                    {feed.is_verified === 1 && (
                      <svg width="13" height="13" viewBox="0 0 24 24" fill="none">
                        <circle cx="12" cy="12" r="12" fill="var(--brand, #C1272D)" />
                        <path d="M7 12l3 3 7-7" stroke="#fff" strokeWidth="2.5" strokeLinecap="round" />
                      </svg>
                    )}
                    {isChannel && (
                      <span style={{ fontSize: 9, fontWeight: 700, letterSpacing: "0.06em", color: "var(--text-3, #9ca3af)", textTransform: "uppercase", padding: "1px 4px", border: "1px solid var(--border, #e5e7eb)", borderRadius: 3 }}>
                        Channel
                      </span>
                    )}
                  </div>
                  <span style={{ fontSize: "0.7rem", fontFamily: "var(--mono)", color: "var(--text-3, #9ca3af)" }}>{fmtRelTime(feed.created_at)}</span>
                </div>
              </>
            );

            return authorHref ? (
              <Link
                href={authorHref}
                style={{ display: "flex", alignItems: "flex-start", gap: "0.75rem", flex: 1, minWidth: 0, textDecoration: "none", color: "inherit" }}
              >
                {avatarAndName}
              </Link>
            ) : (
              <div style={{ display: "flex", alignItems: "flex-start", gap: "0.75rem", flex: 1, minWidth: 0 }}>
                {avatarAndName}
              </div>
            );
          })()}

          {/* ── Menu ── */}
          <div style={{ position: "relative", flexShrink: 0 }}>
            <button
              onClick={() => setMenuOpen((v) => !v)}
              style={{ background: "none", border: "none", cursor: "pointer", padding: "4px 6px", color: "var(--text-secondary)", borderRadius: 6, lineHeight: 0 }}
            >
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                <circle cx="12" cy="5" r="1.5" fill="currentColor" stroke="none" />
                <circle cx="12" cy="12" r="1.5" fill="currentColor" stroke="none" />
                <circle cx="12" cy="19" r="1.5" fill="currentColor" stroke="none" />
              </svg>
            </button>
            {menuOpen && (
              <div style={{ position: "absolute", right: 0, top: "calc(100% + 2px)", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, minWidth: 150, boxShadow: "0 8px 24px rgba(0,0,0,0.12)", zIndex: 50, overflow: "hidden" }}>
                {isOwn && (
                  <button onClick={handleDelete} style={{ display: "flex", alignItems: "center", gap: "0.5rem", width: "100%", padding: "0.625rem 0.875rem", textAlign: "left", background: "none", border: "none", cursor: "pointer", fontSize: "0.8125rem", color: "var(--brand)", fontWeight: 600, borderBottom: "1px solid var(--border)" }}>
                    <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polyline points="3 6 5 6 21 6" /><path d="M19 6l-1 14H6L5 6M10 11v6M14 11v6" /><path d="M9 6V4h6v2" /></svg>
                    Delete post
                  </button>
                )}
                <button onClick={() => { setReportOpen(true); setMenuOpen(false); }} style={{ display: "flex", alignItems: "center", gap: "0.5rem", width: "100%", padding: "0.625rem 0.875rem", textAlign: "left", background: "none", border: "none", cursor: "pointer", fontSize: "0.8125rem", color: "var(--ink)" }}>
                  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z" /><line x1="4" y1="22" x2="4" y2="15" /></svg>
                  Report
                </button>
              </div>
            )}
          </div>
        </div>

        {/* ── Content ── */}
        {feed.title && (
          <p style={{ fontWeight: 600, fontSize: "0.9375rem", lineHeight: 1.45, margin: "0 0 0.25rem", color: "var(--ink)" }}>
            {feed.title}
          </p>
        )}
        {feed.description && feed.description !== feed.title && (
          <p style={{ fontSize: "0.875rem", lineHeight: 1.55, margin: "0 0 0.25rem", color: "var(--text-secondary)" }}>
            {feed.description}
          </p>
        )}
        {feed.hasteg.length > 0 && (
          <div style={{ display: "flex", flexWrap: "wrap", gap: "0.25rem", marginTop: "0.25rem" }}>
            {feed.hasteg.map((h) => (
              <span key={h.id} style={{ fontSize: "0.813rem", color: "var(--brand)", fontWeight: 500 }}>#{h.name.trim()}</span>
            ))}
          </div>
        )}

        {/* ── Media ── */}
        <MediaGrid items={feed.feed_content} />

        {/* ── Action bar ── */}
        <div style={{ display: "flex", gap: "0.25rem", marginTop: "0.75rem", paddingTop: "0.75rem", borderTop: "1px solid var(--border)" }}>
          {/* Like */}
          <button
            onClick={handleLike}
            style={{
              display: "flex", alignItems: "center", gap: "0.375rem",
              background: liked ? "var(--brand-light)" : "none",
              border: "none", cursor: "pointer",
              fontSize: "0.8125rem", fontFamily: "var(--mono)",
              color: liked ? "var(--brand)" : "var(--text-secondary)",
              fontWeight: liked ? 700 : 400,
              padding: "0.375rem 0.625rem", borderRadius: 8,
              transition: "all 0.15s",
            }}
          >
            <svg width="15" height="15" viewBox="0 0 24 24" fill={liked ? "var(--brand)" : "none"} stroke={liked ? "var(--brand)" : "currentColor"} strokeWidth="2">
              <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
            </svg>
            <span>{likeCount > 0 ? likeCount : ""}</span>
          </button>

          {/* Comment */}
          <button
            onClick={() => setCommentOpen(true)}
            style={{
              display: "flex", alignItems: "center", gap: "0.375rem",
              background: commentOpen ? "var(--brand-light)" : "none",
              border: "none", cursor: "pointer",
              fontSize: "0.8125rem", fontFamily: "var(--mono)",
              color: commentOpen ? "var(--brand)" : "var(--text-secondary)",
              padding: "0.375rem 0.625rem", borderRadius: 8,
              transition: "all 0.15s",
            }}
          >
            <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
              <path d="M21 11.5a8.4 8.4 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.4 8.4 0 0 1-3.8-.9L3 21l1.9-5.7a8.4 8.4 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.4 8.4 0 0 1 3.8-.9h.5a8.5 8.5 0 0 1 8 8z" />
            </svg>
            <span>{feed.total_comment > 0 ? feed.total_comment : ""}</span>
          </button>

          {/* Share */}
          <button
            style={{ display: "flex", alignItems: "center", gap: "0.375rem", background: "none", border: "none", cursor: "pointer", fontSize: "0.8125rem", fontFamily: "var(--mono)", color: "var(--text-secondary)", padding: "0.375rem 0.625rem", borderRadius: 8, marginLeft: "auto" }}
          >
            <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
              <circle cx="18" cy="5" r="3" /><circle cx="6" cy="12" r="3" /><circle cx="18" cy="19" r="3" />
              <path d="M8.6 13.5l6.8 4M15.4 6.5l-6.8 4" />
            </svg>
          </button>
        </div>
      </article>

      {/* Comment drawer */}
      <CommentDrawer
        open={commentOpen}
        onClose={() => setCommentOpen(false)}
        type={6}
        contentId={feed.id}
        videoId={0}
        title={feed.title}
      />

      {/* Report modal (not applicable for Feed type 6 — report applies to Articles/Clips/Shows) */}
      <ReportModal
        open={reportOpen}
        onClose={() => setReportOpen(false)}
        type={1}
        contentId={feed.id}
        videoId={0}
      />
    </>
  );
}

// ── Feed Composer ─────────────────────────────────────────────────────────────
function FeedComposer({ userId, onPosted }: { userId: number; onPosted: () => void }) {
  const dispatch = useAppDispatch();
  const isPosting = useAppSelector(selectFeedsPosting);
  const { success, error: showError } = useToast();
  const [open, setOpen] = useState(false);
  const [title, setTitle] = useState("");
  const [desc, setDesc]   = useState("");
  const [tags, setTags]   = useState("");
  const [mediaFiles, setMediaFiles] = useState<{ content_type: string; image: string; video: string; preview?: string }[]>([]);
  const [uploading, setUploading] = useState(false);
  const fileRef = useRef<HTMLInputElement>(null);

  const VIDEO_CHUNK_SIZE = 2 * 1024 * 1024; // 2 MB per chunk

  function extractVideoThumbnail(file: File): Promise<Blob> {
    return new Promise((resolve, reject) => {
      const vid = document.createElement("video");
      vid.muted = true;
      vid.playsInline = true;
      vid.preload = "metadata";
      const url = URL.createObjectURL(file);
      vid.src = url;
      vid.addEventListener("loadedmetadata", () => {
        vid.currentTime = Math.min(1, vid.duration / 3);
      });
      vid.addEventListener("seeked", () => {
        const canvas = document.createElement("canvas");
        canvas.width = vid.videoWidth || 640;
        canvas.height = vid.videoHeight || 360;
        const ctx = canvas.getContext("2d");
        ctx?.drawImage(vid, 0, 0, canvas.width, canvas.height);
        URL.revokeObjectURL(url);
        canvas.toBlob(
          (blob) => blob ? resolve(blob) : reject(new Error("Thumbnail failed")),
          "image/jpeg",
          0.8,
        );
      });
      vid.addEventListener("error", () => {
        URL.revokeObjectURL(url);
        reject(new Error("Video load error"));
      });
    });
  }

  async function handleFileChange(e: React.ChangeEvent<HTMLInputElement>) {
    const files = Array.from(e.target.files ?? []);
    if (!files.length) return;
    setUploading(true);

    for (const file of files) {
      const isVideo = file.type.startsWith("video/");

      if (!isVideo) {
        // ── Image upload (single request) ──────────────────────────────────
        const fd = new FormData();
        fd.append("content_type", "1");
        fd.append("directory", "feed");
        fd.append("image", file);
        const res = await dispatch(uploadFeedContent({ formData: fd }));
        if (uploadFeedContent.fulfilled.match(res)) {
          const r = res.payload;
          setMediaFiles((prev) => [...prev, { content_type: "1", image: r.file_path, video: "", preview: r.file_path }]);
        } else {
          showError("Image upload failed");
        }
        continue;
      }

      // ── Video upload (chunk-based) ────────────────────────────────────────
      let thumb: Blob;
      try {
        thumb = await extractVideoThumbnail(file);
      } catch {
        showError("Could not generate video thumbnail");
        continue;
      }

      const totalChunks = Math.max(1, Math.ceil(file.size / VIDEO_CHUNK_SIZE));
      let lastResult = null;
      let failed = false;

      for (let i = 0; i < totalChunks; i++) {
        const start = i * VIDEO_CHUNK_SIZE;
        const chunk = file.slice(start, Math.min(start + VIDEO_CHUNK_SIZE, file.size));

        const fd = new FormData();
        fd.append("content_type", "2");
        fd.append("directory", "feed");
        fd.append("image", thumb, "thumbnail.jpg");
        fd.append("chunk_index", String(i));
        fd.append("total_chunks", String(totalChunks));
        fd.append("file", chunk, `chunk_${i}`);
        fd.append("video", file, file.name);

        const res = await dispatch(uploadFeedContent({ formData: fd }));
        if (uploadFeedContent.fulfilled.match(res)) {
          lastResult = res.payload;
        } else {
          showError(`Video upload failed at chunk ${i + 1}/${totalChunks}`);
          failed = true;
          break;
        }
      }

      if (!failed && lastResult) {
        setMediaFiles((prev) => [...prev, { content_type: "2", image: "", video: lastResult!.file_path, preview: lastResult!.file_path }]);
      }
    }

    setUploading(false);
    if (fileRef.current) fileRef.current.value = "";
  }

  async function handleSubmit() {
    if (!title.trim()) { showError("Add a title to post"); return; }
    const res = await dispatch(uploadFeed({
      userId,
      categoryId: 1,
      title: title.trim(),
      description: desc.trim(),
      hashtag: tags.trim(),
      feedContent: mediaFiles.map(({ content_type, image, video }) => ({ content_type, image, video })),
    }));
    if (uploadFeed.fulfilled.match(res)) {
      setTitle(""); setDesc(""); setTags(""); setMediaFiles([]); setOpen(false);
      success("Post published");
      onPosted();
    } else {
      showError("Failed to publish post");
    }
  }

  if (!open) {
    return (
      <button
        onClick={() => setOpen(true)}
        style={{
          display: "flex", alignItems: "center", gap: "0.75rem",
          width: "100%", padding: "0.875rem 1rem",
          background: "var(--surface)", border: "1px solid var(--border)",
          borderRadius: 12, cursor: "pointer", marginBottom: "0.75rem",
          textAlign: "left", color: "var(--text-secondary)", fontSize: "0.875rem",
          transition: "border-color 0.15s",
        }}
        onMouseEnter={(e) => (e.currentTarget.style.borderColor = "var(--brand)")}
        onMouseLeave={(e) => (e.currentTarget.style.borderColor = "var(--border)")}
      >
        <div style={{ width: 34, height: 34, borderRadius: "50%", background: "var(--brand-light)", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}>
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--brand)" strokeWidth="2"><circle cx="12" cy="8" r="4" /><path d="M4 21a8 8 0 0 1 16 0" /></svg>
        </div>
        What&apos;s on your mind?
      </button>
    );
  }

  return (
    <div style={{ background: "var(--surface)", border: "1.5px solid var(--brand)", borderRadius: 12, padding: "1rem", marginBottom: "0.75rem" }}>
      <div style={{ display: "flex", gap: "0.75rem" }}>
        <div style={{ flexShrink: 0, width: 36, height: 36, borderRadius: "50%", background: "var(--brand-light)", display: "flex", alignItems: "center", justifyContent: "center" }}>
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--brand)" strokeWidth="2"><circle cx="12" cy="8" r="4" /><path d="M4 21a8 8 0 0 1 16 0" /></svg>
        </div>
        <div style={{ flex: 1 }}>
          <input
            value={title}
            onChange={(e) => setTitle(e.target.value)}
            placeholder="What's happening? *"
            autoFocus
            style={{ width: "100%", border: "none", outline: "none", fontSize: "0.9375rem", color: "var(--ink)", background: "transparent", fontFamily: "var(--sans)", fontWeight: 500, marginBottom: "0.375rem" }}
          />
          <textarea
            value={desc}
            onChange={(e) => setDesc(e.target.value)}
            placeholder="Add details… (optional)"
            rows={2}
            style={{ width: "100%", border: "none", outline: "none", fontSize: "0.875rem", color: "var(--text-secondary)", background: "transparent", resize: "none", fontFamily: "var(--sans)", marginBottom: "0.25rem" }}
          />
          <input
            value={tags}
            onChange={(e) => setTags(e.target.value)}
            placeholder="#hashtags (comma separated)"
            style={{ width: "100%", border: "none", outline: "none", fontSize: "0.8125rem", color: "var(--brand)", background: "transparent", fontFamily: "var(--sans)" }}
          />

          {mediaFiles.length > 0 && (
            <div style={{ display: "flex", gap: "0.5rem", flexWrap: "wrap", marginTop: "0.625rem" }}>
              {mediaFiles.map((m, i) => (
                <div key={i} style={{ position: "relative", width: 68, height: 68, borderRadius: 7, overflow: "hidden", background: "#e5e7eb" }}>
                  {m.preview ? (
                    <Image src={m.preview} alt="" fill style={{ objectFit: "cover" }} unoptimized />
                  ) : (
                    <div style={{ width: "100%", height: "100%", background: "#1e293b", display: "flex", alignItems: "center", justifyContent: "center" }}>
                      <svg width="20" height="20" viewBox="0 0 24 24" fill="rgba(255,255,255,0.4)"><polygon points="6 4 20 12 6 20" /></svg>
                    </div>
                  )}
                  <button onClick={() => setMediaFiles((p) => p.filter((_, j) => j !== i))} style={{ position: "absolute", top: 2, right: 2, width: 16, height: 16, borderRadius: "50%", background: "rgba(0,0,0,0.65)", border: "none", color: "#fff", fontSize: 9, cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", padding: 0, lineHeight: 1 }}>✕</button>
                </div>
              ))}
            </div>
          )}

          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginTop: "0.75rem", paddingTop: "0.75rem", borderTop: "1px solid var(--border)" }}>
            <div style={{ display: "flex", gap: "0.5rem" }}>
              <input ref={fileRef} type="file" accept="image/*,video/*" multiple hidden onChange={handleFileChange} />
              <button onClick={() => fileRef.current?.click()} disabled={uploading} style={{ display: "flex", alignItems: "center", gap: "0.375rem", background: "var(--background)", border: "1px solid var(--border)", borderRadius: 7, padding: "0.375rem 0.75rem", cursor: "pointer", fontSize: "0.8125rem", fontWeight: 600, color: "var(--ink)" }}>
                <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="3" y="3" width="18" height="18" rx="2" /><circle cx="8.5" cy="8.5" r="1.5" /><path d="M21 15l-5-5L5 21" /></svg>
                {uploading ? "Uploading…" : "Media"}
              </button>
              <button onClick={() => { setOpen(false); setTitle(""); setDesc(""); setTags(""); setMediaFiles([]); }} style={{ background: "none", border: "none", cursor: "pointer", fontSize: "0.8125rem", color: "var(--text-secondary)", fontWeight: 500 }}>Cancel</button>
            </div>
            <button onClick={handleSubmit} disabled={!title.trim() || isPosting} style={{ padding: "0.5rem 1.25rem", background: title.trim() ? "var(--brand)" : "#e5e7eb", color: title.trim() ? "#fff" : "var(--text-tertiary)", border: "none", borderRadius: 8, fontWeight: 700, fontSize: "0.875rem", cursor: title.trim() ? "pointer" : "default" }}>
              {isPosting ? "Posting…" : "Post"}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

// ── Skeleton Card ─────────────────────────────────────────────────────────────
function SkeletonCard() {
  return (
    <div style={{ background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 12, padding: "1rem 1.125rem", marginBottom: "0.75rem" }}>
      <div style={{ display: "flex", gap: "0.75rem", marginBottom: "0.75rem" }}>
        <div style={{ flexShrink: 0, width: 38, height: 38, borderRadius: "50%", background: "#e5e7eb" }} />
        <div style={{ flex: 1 }}>
          <div style={{ height: 12, width: "35%", background: "#e5e7eb", borderRadius: 4, marginBottom: 6 }} />
          <div style={{ height: 9, width: "18%", background: "#e5e7eb", borderRadius: 4 }} />
        </div>
      </div>
      <div style={{ height: 14, background: "#e5e7eb", borderRadius: 4, marginBottom: 6 }} />
      <div style={{ height: 14, width: "70%", background: "#e5e7eb", borderRadius: 4, marginBottom: 12 }} />
      <div style={{ height: 140, borderRadius: 8, background: "#e5e7eb" }} />
    </div>
  );
}

// ── Main ──────────────────────────────────────────────────────────────────────
export default function FeedsMain() {
  const dispatch = useAppDispatch();
  const items   = useAppSelector(selectFeedItems);
  const loading = useAppSelector(selectFeedsLoading);
  const hasMore = useAppSelector(selectFeedsHasMore);
  const page    = useAppSelector(selectFeedsPage);
  const fetchedRef = useRef(false);

  // Start as 0 on both server and client to avoid hydration mismatch.
  // localStorage is only available on the client, so we read it in useEffect.
  const [userId, setUserId] = useState(0);
  useEffect(() => {
    setUserId(getStoredUser()?.id ?? 0);
  }, []);

  const load = useCallback((p: number) => {
    dispatch(fetchFeed({ userId, page: p }));
  }, [dispatch, userId]);

  useEffect(() => {
    if (!fetchedRef.current) {
      fetchedRef.current = true;
      load(1);
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <div className="feeds-main">
      {userId > 0 && <FeedComposer userId={userId} onPosted={() => load(1)} />}

      {loading && items.length === 0 ? (
        <>
          <SkeletonCard /><SkeletonCard /><SkeletonCard />
        </>
      ) : items.length === 0 ? (
        <div style={{ background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 12, padding: "3rem 1.5rem", textAlign: "center" }}>
          <p style={{ fontWeight: 700, fontSize: "1rem", marginBottom: "0.375rem", color: "var(--ink)" }}>Your feed is empty</p>
          <p style={{ fontSize: "0.875rem", color: "var(--text-secondary)" }}>Follow channels to see their posts here</p>
        </div>
      ) : (
        <>
          {items.map((feed) => <FeedCard key={feed.id} feed={feed} userId={userId} />)}

          {hasMore && (
            <button
              onClick={() => load(page + 1)}
              disabled={loading}
              style={{ display: "block", width: "100%", padding: "0.75rem", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 10, fontWeight: 600, fontSize: "0.875rem", color: "var(--brand)", cursor: "pointer", marginTop: "0.25rem" }}
            >
              {loading ? "Loading…" : "Load more posts"}
            </button>
          )}
        </>
      )}
    </div>
  );
}
