import type { Route } from "../+types/root";
import { useState, useEffect, type FormEventHandler } from "react";

import RootLayout from "~/layout/RootLayout";
import { getTagColor } from "../utils/tags";
import type { Post } from "../types/post";

import Icon, { ICONS } from "../components/Icon";

import { API } from "../api/api";
import { useNavigate } from "react-router";
import type { PaginatedResponse } from "~/types/PaginatedResponse";
import Loading from "~/components/Loading";
import { getApiErrorMessage } from "~/context/AuthContext";

interface PostCardProps {
  post: Post;
  onClick: (id: number) => void;
}

export function meta({}: Route.MetaArgs) {
  return [
    { title: "ImgBoard - Posts" },
  ];
}

export default function Posts() {

  const PostCard = ({ post, onClick }: PostCardProps) => (
    <div className="bg-white rounded-lg shadow-md overflow-hidden cursor-pointer transform hover:-translate-y-1 transition-transform duration-300" onClick={() => onClick(post.id)}>
      <img src={post.fileUrl} alt={post.title} className="w-full h-48 object-cover" />
      <div className="p-4">
        <h3 className="font-bold text-lg truncate">{post.title}</h3>
        <div className="flex flex-wrap gap-1 mt-2">
          {post.tags.slice(0, 3).map(tag => (
            <span key={tag.name} className={`text-xs font-semibold px-2 py-1 rounded-full ${getTagColor(tag)}`}>
              {tag.name}
            </span>
          ))}
          {post.tags.length > 3 && <span className="text-gray-500 text-xs font-semibold py-1">...</span>}
        </div>
      </div>
    </div>
  );


  const SearchBar = ({ currentQuery, onSearch }: { currentQuery: string, onSearch: (query: string) => void }) => {
    const [query, setQuery] = useState(currentQuery);

    const handleSearch: FormEventHandler = (e) => {
      e.preventDefault();
      onSearch(query);
    };

    return (
      <div className="p-4 md:px-6 md:pt-6">
        <form onSubmit={handleSearch} className="max-w-xl mx-auto">
          <div className="relative">
            <input type="text" value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Search posts by tags (e.g., +high-res -theotown)" className="w-full px-5 py-3 text-gray-700 bg-white border-2 border-gray-200 rounded-full focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors"/>
            <button type="submit" className="absolute top-0 right-0 mt-3 mr-4 text-gray-400 hover:text-gray-600">
              <Icon path={ICONS.search}/>
            </button>
          </div>
        </form>
      </div>
    );
  };

  const GridView = ({ posts, onPostSelect }: { posts: Post[]; onPostSelect: (id: number) => void }) => (
    <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6 p-4 md:p-6">
      {posts.map(post => <PostCard key={post.id} post={post} onClick={onPostSelect} />)}
    </div>
  );

  const Pagination = ({
    postsPerPage,
    totalPosts,
    paginate,
    currentPage,
  }: {
    postsPerPage: number;
    totalPosts: number;
    paginate: (pageNumber: number) => void;
    currentPage: number;
  }) => {
    const pageNumbers = [];
    for (let i = 1; i <= Math.ceil(totalPosts / postsPerPage); i++) { pageNumbers.push(i); }
    if(pageNumbers.length <= 1) return null;
    return (
      <nav className="mt-8 flex justify-center">
        <ul className="flex items-center space-x-2">
          {pageNumbers.map(number => (
            <li key={number}>
              <button onClick={() => paginate(number)} className={`px-4 py-2 rounded-md transition-colors ${ currentPage === number ? 'bg-blue-500 text-white' : 'bg-white text-gray-700 hover:bg-gray-100'}`}>
                {number}
              </button>
            </li>
          ))}
        </ul>
      </nav>
    );
  };

  const [paginatedData, setPaginatedData] = useState<PaginatedResponse<Post> | null>(null);
  const [currentPage, setCurrentPage] = useState(1);
  const [searchQuery, setSearchQuery] = useState('');

  const navigate = useNavigate();

  useEffect(() => {
    setCurrentPage(1);
  }, [searchQuery])

  useEffect(() => {
    const fetchData = async () => {
      try {
        const data = await API.fetchPosts(currentPage, searchQuery);
        setPaginatedData(data);
      } catch (err: any) {
        alert(`Failed to fetch posts: ${getApiErrorMessage(err)}`);
      }
    }
    fetchData();
  }, [currentPage, searchQuery]);

  const handleSearch = (query: string) => { setSearchQuery(query); setCurrentPage(1); };
  const handlePostSelect = (id: number) => { navigate(`/posts/${id}`) };

  const currentPosts = paginatedData?.items ?? [];
  const paginate = (pageNumber: number) => setCurrentPage(pageNumber);

  if (!paginatedData) {
    return <RootLayout>
      <Loading />
    </RootLayout>;
  }

  return (
    <RootLayout>
    {paginatedData.items.length > 0 ?
      <>
        <SearchBar currentQuery={searchQuery} onSearch={handleSearch} />
        <GridView posts={currentPosts} onPostSelect={handlePostSelect} />
        <Pagination postsPerPage={paginatedData.pageSize} totalPosts={paginatedData.totalCount} paginate={paginate} currentPage={currentPage} />
      </>
      :
      <div className="p-4 md:p-6 max-w-4xl mx-auto">
        <div className="bg-white rounded-xl shadow-lg p-6 text-center">
          <h2 className="text-2xl font-bold mb-4 text-gray-800">No Posts Found</h2>
          <p className="text-gray-600 mb-6">Try adjusting your search to find what you're looking for.</p>
          <button onClick={() => { setSearchQuery(''); setCurrentPage(1); }} className="bg-blue-500 text-white font-semibold px-4 py-2 rounded-md hover:bg-blue-600 transition-colors">
            Clear Search
          </button>
        </div>
      </div>
    }
    </RootLayout>
  );
}
