import { useState, useEffect, useRef, useCallback } from "react";

// =============================================
// Mock API (DO NOT MODIFY)
// =============================================
// Simulates /api/v1/posts?page=1&limit=10
// Returns { data: Post[], meta: Meta }

interface Post {
  id: number;
  title: string;
  body: string;
  author: string;
  createdAt: string;
}

interface Meta {
  page: number;
  limit: number;
  total: number;
  totalPages: number;
  hasMore: boolean;
}

const ALL_POSTS: Post[] = Array.from({ length: 100 }, (_, i) => ({
  id: i + 1,
  title: `Post #${i + 1}`,
  body: `This is the body of post ${i + 1}. It contains some sample text to simulate a real feed item you might see in a social media app or blog.`,
  author: `user_${(i % 12) + 1}`,
  createdAt: new Date(Date.now() - i * 3600000).toISOString(),
}));

async function fetchPosts(page: number, limit = 10): Promise<{ data: Post[]; meta: Meta }> {
  // Simulate network latency
  await new Promise((r) => setTimeout(r, 500));
  const start = (page - 1) * limit;
  const end = start + limit;
  return {
    data: ALL_POSTS.slice(start, end),
    meta: {
      page,
      limit,
      total: ALL_POSTS.length,
      totalPages: Math.ceil(ALL_POSTS.length / limit),
      hasMore: end < ALL_POSTS.length,
    },
  };
}

// =============================================
// TODO: Implement Infinite Scroll
// =============================================
//
// Requirements:
//   1. Load the first page of posts on mount
//   2. Display posts in a scrollable list
//   3. Automatically load the next page when the user
//      scrolls near the bottom (no "Load More" button)
//   4. Show a loading spinner while fetching
//   5. Show an "end of list" message when all posts are loaded
//   6. Don't fetch if already loading or no more pages
//
// Approach — IntersectionObserver:
//   - Create a "sentinel" div at the bottom of the list
//   - Use IntersectionObserver to watch it
//   - When it enters the viewport → fetch next page
//   - Disconnect/reconnect observer as needed
//
// Hints:
//   - useRef to hold the IntersectionObserver instance
//   - useCallback ref on the sentinel element
//   - Check meta.hasMore before fetching
//   - Append new posts to existing: setPosts(prev => [...prev, ...newData])
//   - Guard against double-fetches with a loading flag

export default function App() {
  const [posts, setPosts] = useState<Post[]>([]);
  const [meta, setMeta] = useState<Meta | null>(null);
  const [page, setPage] = useState(1);
  const [loading, setLoading] = useState(false);

  // TODO: Create a ref to hold the IntersectionObserver
  // const observer = useRef<IntersectionObserver | null>(null);

  // =============================================
  // TODO: Implement loadPage
  // =============================================
  // Should:
  //   - Set loading to true
  //   - Call fetchPosts(pageNum)
  //   - Append results to posts state
  //   - Update meta state
  //   - Set loading to false
  const loadPage = async (pageNum: number) => {
    // Your code here
  };

  // =============================================
  // TODO: Implement the sentinel ref callback
  // =============================================
  // This function receives the sentinel DOM node.
  // It should:
  //   1. Return early if loading
  //   2. Disconnect any existing observer
  //   3. Create a new IntersectionObserver that calls loadMore
  //      when the sentinel is intersecting AND meta.hasMore
  //   4. Observe the node
  //
  // Wrap with useCallback and include [loading, meta, page]
  // in the dependency array
  //
  // const sentinelRef = useCallback((node: HTMLDivElement | null) => {
  //   // Your code here
  // }, [loading, meta, page]);

  // =============================================
  // TODO: Load first page on mount
  // =============================================
  // useEffect(() => {
  //   loadPage(1);
  // }, []);

  return (
    <div style={{ maxWidth: 600, margin: "0 auto", padding: 24, fontFamily: "system-ui" }}>
      <h2 style={{ fontSize: 20, fontWeight: 700, marginBottom: 4 }}>
        Infinite Scroll
      </h2>
      <p style={{ fontSize: 14, color: "#666", marginBottom: 24 }}>
        Implement infinite scrolling using IntersectionObserver.
        Posts load from a mock API with 500ms latency.
      </p>

      {/* Stats bar */}
      <div style={{
        display: "flex",
        justifyContent: "space-between",
        padding: "10px 14px",
        background: "#f9fafb",
        border: "1px solid #e5e7eb",
        borderRadius: 8,
        fontSize: 13,
        marginBottom: 20,
      }}>
        <span>
          Showing <strong>{posts.length}</strong> of <strong>{meta?.total ?? "..."}</strong> posts
        </span>
        <span style={{ color: "#999" }}>
          Page {page} / {meta?.totalPages ?? "..."}
        </span>
      </div>

      {/* Post list */}
      <div style={{ height: "60vh", overflowY: "auto", display: "flex", flexDirection: "column", gap: 12 }}>
        {posts.map((post) => (
          <article
            key={post.id}
            style={{
              border: "1px solid #e5e7eb",
              borderRadius: 8,
              padding: 16,
            }}
          >
            <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }}>
              <div style={{
                width: 28,
                height: 28,
                borderRadius: "50%",
                background: "#e5e7eb",
                display: "flex",
                alignItems: "center",
                justifyContent: "center",
                fontSize: 11,
                fontWeight: 600,
                color: "#666",
              }}>
                {post.author.slice(-2)}
              </div>
              <span style={{ fontSize: 13, color: "#666" }}>{post.author}</span>
              <span style={{ color: "#ccc", fontSize: 11 }}>·</span>
              <time style={{ fontSize: 11, color: "#999" }}>
                {new Date(post.createdAt).toLocaleDateString()}
              </time>
            </div>
            <h3 style={{ fontSize: 15, fontWeight: 600, marginBottom: 4 }}>{post.title}</h3>
            <p style={{ fontSize: 13, color: "#666", lineHeight: 1.6, margin: 0 }}>{post.body}</p>
          </article>
        ))}

        {/* ============================================= */}
        {/* TODO: Add a sentinel div here                 */}
        {/* ============================================= */}
        {/* 
          This invisible div sits at the bottom of the list.
          Attach your sentinelRef to it so IntersectionObserver
          can detect when the user scrolls to the bottom.
          
          Example: <div ref={sentinelRef} style={{ height: 1 }} />
        */}
      </div>

      {/* Loading spinner */}
      {loading && (
        <div style={{ display: "flex", justifyContent: "center", padding: 24 }}>
          <div style={{
            width: 24,
            height: 24,
            border: "2px solid #e5e7eb",
            borderTopColor: "#111",
            borderRadius: "50%",
            animation: "spin 0.6s linear infinite",
          }} />
        </div>
      )}

      {/* End state */}
      {meta && !meta.hasMore && posts.length > 0 && (
        <p style={{ textAlign: "center", color: "#999", fontSize: 13, padding: 24 }}>
          You've reached the end — {meta.total} posts loaded.
        </p>
      )}

      {/* Fallback button (remove once auto-scroll works) */}
      {meta?.hasMore && !loading && (
        <div style={{ display: "flex", justifyContent: "center", padding: 20 }}>
          <button
            onClick={() => {
              const next = page + 1;
              setPage(next);
              loadPage(next);
            }}
            style={{
              padding: "10px 24px",
              background: "#111",
              color: "#fff",
              borderRadius: 999,
              fontSize: 13,
              fontWeight: 600,
              cursor: "pointer",
            }}
          >
            Load More
          </button>
        </div>
      )}

      {/* Hint */}
      <div style={{
        marginTop: 24,
        padding: 16,
        background: "#f9fafb",
        borderLeft: "4px solid #111",
        borderRadius: "0 8px 8px 0",
        fontSize: 13,
        color: "#555",
      }}>
        <strong>Goal:</strong> Remove the "Load More" button and replace it with
        automatic loading. Add a sentinel <code>&lt;div ref=&#123;sentinelRef&#125; /></code> at
        the bottom of the post list. When IntersectionObserver detects it's visible,
        fetch the next page. Guard against double-fetches with the loading flag.
      </div>
    </div>
  );
}