import { useEffect, useState } from "react";
import { Link } from "react-router-dom";

interface Episode {
  id: string;
  title: string;
  description: string;
  pubDate: string;
  audioUrl: string;
  audioLength: string;
  guid: string;
  link: string;
}

interface EpisodeWithFeedInfo {
  id: string;
  title: string;
  description?: string;
  audioPath: string;
  duration?: number;
  fileSize?: number;
  createdAt: string;
  articleId: string;
  articleTitle: string;
  articleLink: string;
  articlePubDate: string;
  feedId: string;
  feedTitle?: string;
  feedUrl: string;
  feedCategory?: string;
  category?: string;
}

function EpisodeList() {
  const [episodes, setEpisodes] = useState<EpisodeWithFeedInfo[]>([]);
  const [filteredEpisodes, setFilteredEpisodes] = useState<
    EpisodeWithFeedInfo[]
  >([]);
  const [categories, setCategories] = useState<string[]>([]);
  const [selectedCategory, setSelectedCategory] = useState<string>("");
  const [searchQuery, setSearchQuery] = useState<string>("");
  const [isSearching, setIsSearching] = useState(false);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [currentAudio, setCurrentAudio] = useState<string | null>(null);
  const [useDatabase, setUseDatabase] = useState(true);
  // Pagination state
  const [currentPage, setCurrentPage] = useState<number>(1);
  const [pageSize, setPageSize] = useState<number>(20);
  const [totalPages, setTotalPages] = useState<number>(1);
  const [totalEpisodes, setTotalEpisodes] = useState<number>(0);

  useEffect(() => {
    fetchEpisodes();
    fetchCategories();
  }, [useDatabase, currentPage, pageSize]);

  useEffect(() => {
    if (searchQuery.trim()) {
      performSearch();
    } else if (!useDatabase) {
      // Only filter locally if using XML data (non-paginated)
      filterEpisodesByCategory();
    }
  }, [episodes, selectedCategory, searchQuery]);

  // Reset to page 1 when category changes (but don't trigger if already on page 1)
  useEffect(() => {
    if (currentPage !== 1) {
      setCurrentPage(1);
    } else {
      // If already on page 1, still need to refetch with new category
      fetchEpisodes();
    }
  }, [selectedCategory]);

  const fetchEpisodes = async () => {
    try {
      setLoading(true);
      setError(null);

      if (useDatabase) {
        // Try to fetch from database first with pagination
        const searchParams = new URLSearchParams({
          page: currentPage.toString(),
          limit: pageSize.toString(),
        });

        if (selectedCategory) {
          searchParams.append("category", selectedCategory);
        }

        const response = await fetch(
          `/api/episodes-with-feed-info?${searchParams}`,
        );
        if (!response.ok) {
          throw new Error("データベースからの取得に失敗しました");
        }
        const data = await response.json();

        // Handle paginated response
        if (data.episodes !== undefined) {
          const dbEpisodes = data.episodes || [];

          if (dbEpisodes.length === 0 && data.total === 0) {
            // Database is empty, fallback to XML
            console.log("Database is empty, falling back to XML parsing...");
            setUseDatabase(false);
            return;
          }

          setEpisodes(dbEpisodes);
          setTotalEpisodes(data.total || 0);
          setTotalPages(data.totalPages || 1);
          setFilteredEpisodes(dbEpisodes); // For paginated data, episodes are already filtered
        } else {
          // Fallback to non-paginated response
          const dbEpisodes = data.episodes || [];
          if (dbEpisodes.length === 0) {
            console.log("Database is empty, falling back to XML parsing...");
            setUseDatabase(false);
            return;
          }
          setEpisodes(dbEpisodes);
        }
      } else {
        // Use XML parsing as primary source
        const response = await fetch("/api/episodes-from-xml");
        if (!response.ok) {
          const errorData = await response.json();
          throw new Error(errorData.error || "エピソードの取得に失敗しました");
        }
        const data = await response.json();
        console.log("Fetched episodes from XML:", data);

        // Convert XML episodes to EpisodeWithFeedInfo format
        const xmlEpisodes = data.episodes || [];
        const convertedEpisodes: EpisodeWithFeedInfo[] = xmlEpisodes.map(
          (episode: Episode) => ({
            id: episode.id,
            title: episode.title,
            description: episode.description,
            audioPath: episode.audioUrl,
            createdAt: episode.pubDate,
            articleId: episode.guid,
            articleTitle: episode.title,
            articleLink: episode.link,
            articlePubDate: episode.pubDate,
            feedId: "",
            feedTitle: "RSS Feed",
            feedUrl: "",
          }),
        );
        setEpisodes(convertedEpisodes);
      }
    } catch (err) {
      console.error("Episode fetch error:", err);
      if (useDatabase) {
        // Fallback to XML if database fails
        console.log("Falling back to XML parsing...");
        setUseDatabase(false);
        return;
      }
      setError(err instanceof Error ? err.message : "エラーが発生しました");
    } finally {
      setLoading(false);
    }
  };

  const fetchCategories = async () => {
    try {
      const response = await fetch("/api/episode-categories");
      if (response.ok) {
        const data = await response.json();
        setCategories(data.categories || []);
      }
    } catch (err) {
      console.error("Error fetching categories:", err);
    }
  };

  const performSearch = async () => {
    try {
      setIsSearching(true);
      setError(null);

      const searchParams = new URLSearchParams({
        q: searchQuery.trim(),
      });

      if (selectedCategory) {
        searchParams.append("category", selectedCategory);
      }

      const response = await fetch(`/api/episodes/search?${searchParams}`);
      if (!response.ok) {
        throw new Error("検索に失敗しました");
      }

      const data = await response.json();
      setFilteredEpisodes(data.episodes || []);
    } catch (err) {
      console.error("Search error:", err);
      setError(err instanceof Error ? err.message : "検索エラーが発生しました");
      setFilteredEpisodes([]);
    } finally {
      setIsSearching(false);
    }
  };

  const filterEpisodesByCategory = () => {
    if (!selectedCategory) {
      setFilteredEpisodes(episodes);
    } else {
      const filtered = episodes.filter(
        (ep) => ep.category === selectedCategory,
      );
      setFilteredEpisodes(filtered);
    }
  };

  const formatDate = (dateString: string) => {
    return new Date(dateString).toLocaleString("ja-JP");
  };

  const playAudio = (audioPath: string) => {
    if (currentAudio) {
      const currentPlayer = document.getElementById(
        currentAudio,
      ) as HTMLAudioElement;
      if (currentPlayer) {
        currentPlayer.pause();
        currentPlayer.currentTime = 0;
      }
    }
    setCurrentAudio(audioPath);
  };

  const shareEpisode = (episode: EpisodeWithFeedInfo) => {
    const shareUrl = `${window.location.origin}/episode/${episode.id}`;
    navigator.clipboard
      .writeText(shareUrl)
      .then(() => {
        alert("エピソードリンクをクリップボードにコピーしました");
      })
      .catch(() => {
        // Fallback for older browsers
        const textArea = document.createElement("textarea");
        textArea.value = shareUrl;
        document.body.appendChild(textArea);
        textArea.select();
        document.execCommand("copy");
        document.body.removeChild(textArea);
        alert("エピソードリンクをクリップボードにコピーしました");
      });
  };

  const formatFileSize = (bytes?: number) => {
    if (!bytes) return "";

    const units = ["B", "KB", "MB", "GB"];
    let unitIndex = 0;
    let fileSize = bytes;

    while (fileSize >= 1024 && unitIndex < units.length - 1) {
      fileSize /= 1024;
      unitIndex++;
    }

    return `${fileSize.toFixed(1)} ${units[unitIndex]}`;
  };

  if (loading) {
    return <div className="loading">読み込み中...</div>;
  }

  if (error) {
    return <div className="error">{error}</div>;
  }

  if (filteredEpisodes.length === 0 && episodes.length > 0) {
    if (searchQuery.trim()) {
      return (
        <div className="empty-state">
          <p>「{searchQuery}」の検索結果がありません</p>
          {selectedCategory && (
            <p>カテゴリ「{selectedCategory}」内で検索しています</p>
          )}
          <div
            style={{
              marginTop: "10px",
              display: "flex",
              gap: "10px",
              justifyContent: "center",
            }}
          >
            <button
              className="btn btn-secondary"
              onClick={() => setSearchQuery("")}
            >
              検索をクリア
            </button>
            {selectedCategory && (
              <button
                className="btn btn-secondary"
                onClick={() => setSelectedCategory("")}
              >
                全カテゴリで検索
              </button>
            )}
          </div>
        </div>
      );
    } else if (selectedCategory) {
      return (
        <div className="empty-state">
          <p>カテゴリ「{selectedCategory}」のエピソードがありません</p>
          <button
            className="btn btn-secondary"
            onClick={() => setSelectedCategory("")}
            style={{ marginTop: "10px" }}
          >
            全てのエピソードを表示
          </button>
        </div>
      );
    }
  }

  if (episodes.length === 0) {
    return (
      <div className="empty-state">
        <p>エピソードがありません</p>
        <p>
          フィードリクエストでRSSフィードをリクエストするか、管理者にバッチ処理の実行を依頼してください
        </p>
        <button
          className="btn btn-secondary"
          onClick={fetchEpisodes}
          style={{ marginTop: "10px" }}
        >
          再読み込み
        </button>
      </div>
    );
  }

  return (
    <div>
      <div style={{ marginBottom: "20px" }}>
        <div className="episode-header">
          <h2 className="episode-title">
            エピソード一覧 (
            {searchQuery
              ? `検索結果: ${filteredEpisodes.length}件`
              : useDatabase
                ? `${totalEpisodes}件中 ${Math.min((currentPage - 1) * pageSize + 1, totalEpisodes)}-${Math.min(currentPage * pageSize, totalEpisodes)}件を表示 (${currentPage}/${totalPages}ページ)`
                : selectedCategory
                  ? `${filteredEpisodes.length}/${episodes.length}件`
                  : `${episodes.length}件`}
            )
          </h2>
          <div className="episode-meta">
            <span className="episode-meta-text">
              データソース: {useDatabase ? "データベース" : "XML"}
            </span>
            <button className="btn btn-secondary" onClick={fetchEpisodes}>
              更新
            </button>
          </div>
        </div>

        <div className="episode-search-bar">
          <input
            type="text"
            placeholder="エピソードを検索..."
            value={searchQuery}
            onChange={(e) => setSearchQuery(e.target.value)}
            className="episode-search-input"
          />
          {searchQuery && (
            <button
              className="btn btn-secondary"
              onClick={() => setSearchQuery("")}
              style={{
                padding: "8px 12px",
                fontSize: "14px",
              }}
            >
              クリア
            </button>
          )}
          {categories.length > 0 && (
            <select
              value={selectedCategory}
              onChange={(e) => setSelectedCategory(e.target.value)}
              className="episode-category-select"
            >
              <option value="">全カテゴリ</option>
              {categories.map((category) => (
                <option key={category} value={category}>
                  {category}
                </option>
              ))}
            </select>
          )}
          {isSearching && <span className="episode-meta-text">検索中...</span>}
        </div>
      </div>

      <table className="table">
        <thead>
          <tr>
            <th style={{ width: "35%" }}>タイトル</th>
            <th style={{ width: "25%" }}>説明</th>
            <th style={{ width: "15%" }}>作成日</th>
            <th style={{ width: "25%" }}>操作</th>
          </tr>
        </thead>
        <tbody>
          {filteredEpisodes.map((episode) => (
            <tr key={episode.id}>
              <td>
                <div style={{ marginBottom: "8px" }}>
                  <strong>
                    <Link
                      to={`/episode/${episode.id}`}
                      className="episode-link"
                    >
                      {episode.title}
                    </Link>
                  </strong>
                </div>
                {episode.feedTitle && (
                  <div className="episode-feed-info">
                    フィード:{" "}
                    <Link
                      to={`/feeds/${episode.feedId}`}
                      className="episode-link"
                    >
                      {episode.feedTitle}
                    </Link>
                    {episode.feedCategory && (
                      <span
                        style={{
                          marginLeft: "8px",
                          color: "var(--text-muted)",
                          fontSize: "11px",
                        }}
                      >
                        ({episode.feedCategory})
                      </span>
                    )}
                  </div>
                )}
                {episode.articleTitle &&
                  episode.articleTitle !== episode.title && (
                    <div className="episode-article-info">
                      元記事: <strong>{episode.articleTitle}</strong>
                    </div>
                  )}
                {episode.articleLink && (
                  <a
                    href={episode.articleLink}
                    target="_blank"
                    rel="noopener noreferrer"
                    className="episode-article-link"
                  >
                    元記事を見る
                  </a>
                )}
              </td>
              <td>
                <div className="episode-description">
                  {episode.description || "No description"}
                </div>
                {episode.fileSize && (
                  <div className="episode-file-size">
                    {formatFileSize(episode.fileSize)}
                  </div>
                )}
              </td>
              <td>{formatDate(episode.createdAt)}</td>
              <td>
                <div className="episode-actions">
                  <div className="episode-action-buttons">
                    <button
                      className="btn btn-primary"
                      onClick={() =>
                        playAudio(
                          episode.audioPath.startsWith("/")
                            ? episode.audioPath
                            : `/podcast_audio/${episode.audioPath}`,
                        )
                      }
                    >
                      再生
                    </button>
                    <button
                      className="btn btn-secondary"
                      onClick={() => shareEpisode(episode)}
                    >
                      共有
                    </button>
                  </div>
                  {currentAudio ===
                    (episode.audioPath.startsWith("/")
                      ? episode.audioPath
                      : `/podcast_audio/${episode.audioPath}`) && (
                    <div>
                      <audio
                        id={episode.audioPath}
                        controls
                        className="audio-player"
                        src={
                          episode.audioPath.startsWith("/")
                            ? episode.audioPath
                            : `/podcast_audio/${episode.audioPath}`
                        }
                        onEnded={() => setCurrentAudio(null)}
                      />
                    </div>
                  )}
                </div>
              </td>
            </tr>
          ))}
        </tbody>
      </table>

      {/* Pagination Controls - only show for database mode */}
      {useDatabase && totalPages > 1 && (
        <div className="pagination-container">
          <button
            className="btn btn-secondary"
            onClick={() => setCurrentPage(Math.max(1, currentPage - 1))}
            disabled={currentPage === 1}
          >
            前へ
          </button>

          {/* Page numbers */}
          <div className="pagination-pages">
            {/* First page */}
            {currentPage > 3 && (
              <>
                <button
                  className={`btn ${currentPage === 1 ? "btn-primary" : "btn-secondary"}`}
                  onClick={() => setCurrentPage(1)}
                >
                  1
                </button>
                {currentPage > 4 && <span>...</span>}
              </>
            )}

            {/* Current page and nearby pages */}
            {Array.from({ length: Math.min(5, totalPages) }, (_, i) => {
              const pageNum = Math.max(1, currentPage - 2) + i;
              if (pageNum > totalPages) return null;
              if (pageNum < Math.max(1, currentPage - 2)) return null;

              return (
                <button
                  key={pageNum}
                  className={`btn pagination-page-btn ${currentPage === pageNum ? "btn-primary" : "btn-secondary"}`}
                  onClick={() => setCurrentPage(pageNum)}
                >
                  {pageNum}
                </button>
              );
            })}

            {/* Last page */}
            {currentPage < totalPages - 2 && (
              <>
                {currentPage < totalPages - 3 && <span>...</span>}
                <button
                  className={`btn ${currentPage === totalPages ? "btn-primary" : "btn-secondary"}`}
                  onClick={() => setCurrentPage(totalPages)}
                >
                  {totalPages}
                </button>
              </>
            )}
          </div>

          <button
            className="btn btn-secondary"
            onClick={() =>
              setCurrentPage(Math.min(totalPages, currentPage + 1))
            }
            disabled={currentPage === totalPages}
          >
            次へ
          </button>

          {/* Page size selector */}
          <div className="pagination-size-selector">
            <span style={{ fontSize: "14px" }}>表示件数:</span>
            <select
              value={pageSize}
              onChange={(e) => {
                setPageSize(Number.parseInt(e.target.value, 10));
                setCurrentPage(1); // Reset to first page when changing page size
              }}
              className="pagination-size-select"
            >
              <option value={10}>10</option>
              <option value={20}>20</option>
              <option value={50}>50</option>
              <option value={100}>100</option>
            </select>
          </div>
        </div>
      )}
    </div>
  );
}

export default EpisodeList;
