<!doctype html>
<html lang="en">
  {% from "partials/header.html" import header with context %}
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>{{ app_name }} v{{ app_version }} - Hashtag Streams</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
    />

    <!-- Favicon -->
    <link rel="icon" href="/static/FenLiu.png" type="image/png" />
    <link rel="apple-touch-icon" href="/static/FenLiu.png" />
  </head>
  <body class="bg-gray-50 min-h-screen">
    {{ header('streams') }}

    <main class="container mx-auto px-4 py-8">
      <!-- Flash message area -->
      <div id="flash" class="hidden mb-4"></div>

      <div class="mb-8">
        <h2 class="text-3xl font-bold text-gray-800">Hashtag Streams</h2>
        <p class="text-gray-600 mt-2">
          Monitor and manage Fediverse hashtag streams.
        </p>
      </div>

      <div class="bg-white rounded-lg shadow-md p-6 mb-8">
        <h3 class="text-xl font-bold text-gray-800 mb-6">
          <i class="fas fa-plus-circle mr-2 text-green-500"></i>Add New Stream
        </h3>
        <form id="addStreamForm" class="space-y-4">
          <div>
            <label class="block text-gray-700 mb-2" for="hashtag"
              >Hashtag</label
            >
            <input
              type="text"
              id="hashtag"
              name="hashtag"
              class="w-full px-4 py-2 border border-gray-300 rounded-lg"
              placeholder="#example"
              required
            />
            <p class="text-gray-500 text-sm mt-1">Enter without the # symbol</p>
          </div>
          <div>
            <label class="block text-gray-700 mb-2" for="instance"
              >Instance</label
            >
            <input
              type="text"
              id="instance"
              name="instance"
              class="w-full px-4 py-2 border border-gray-300 rounded-lg"
              placeholder="mastodon.social"
              value="{{ default_instance }}"
              required
            />
          </div>
          <div class="flex items-center">
            <input
              type="checkbox"
              id="active"
              name="active"
              class="mr-2"
              checked
            />
            <label for="active" class="text-gray-700">Active</label>
          </div>
          <button
            type="submit"
            class="w-full bg-green-500 text-white py-3 rounded-lg font-semibold hover:bg-green-600"
          >
            <i class="fas fa-plus mr-2"></i>Add Stream
          </button>
        </form>
      </div>

      <div class="bg-white rounded-lg shadow-md p-6">
        <div class="flex justify-between items-center mb-6">
          <h3 class="text-xl font-bold text-gray-800">
            <i class="fas fa-list mr-2 text-blue-500"></i>Streams
          </h3>
          <div class="flex items-center space-x-4">
            <button
              id="fetchAllBtn"
              class="bg-blue-500 text-white px-4 py-2 rounded-lg font-semibold hover:bg-blue-600"
            >
              <i class="fas fa-cloud-download-alt mr-2"></i>Fetch All Active
              Streams
            </button>
            <span
              class="bg-blue-100 text-blue-800 text-sm font-semibold px-3 py-1 rounded-full"
            >
              {{ streams|length }} streams
            </span>
          </div>
        </div>

        {% if streams %}
        <div class="space-y-4">
          {% for stream in streams %}
          <div class="border border-gray-200 rounded-lg p-4">
            <div class="flex justify-between items-start">
              <div>
                <div class="flex items-center">
                  <h4 class="text-lg font-semibold text-gray-800">
                    <i class="fas fa-hashtag mr-2 text-indigo-500"></i>#{{
                    stream.hashtag }}
                  </h4>
                  {% if stream.active %}
                  <span
                    class="ml-3 bg-green-100 text-green-800 text-xs font-semibold px-2 py-1 rounded"
                  >
                    <i class="fas fa-play mr-1"></i>Active
                  </span>
                  {% else %}
                  <span
                    class="ml-3 bg-gray-100 text-gray-800 text-xs font-semibold px-2 py-1 rounded"
                  >
                    <i class="fas fa-pause mr-1"></i>Paused
                  </span>
                  {% endif %}
                </div>
                <p class="text-gray-600 mt-1">
                  <i class="fas fa-server mr-1"></i>{{ stream.instance }}
                </p>
                <p class="text-gray-500 text-sm mt-2">
                  <i class="far fa-clock mr-1"></i>Created {{ stream.created_at
                  }}
                </p>
                {% if stream.last_check %}
                <p class="text-gray-500 text-sm">
                  <i class="fas fa-sync-alt mr-1"></i>Last fetched {{
                  stream.last_check }}
                  {% if stream.last_fetch_count is not none %}
                  <span class="ml-1 text-xs text-gray-400">({{ stream.last_fetch_count }} fetched)</span>
                  {% endif %}
                </p>
                {% endif %} {% if stream.enable_scheduling %}
                <p class="text-blue-600 text-sm mt-2">
                  <i class="fas fa-clock mr-1"></i>Fetching every {{
                  stream.fetch_interval_minutes }} minutes
                </p>
                {% if stream.next_scheduled_fetch %}
                <p class="text-blue-500 text-sm">
                  <i class="fas fa-hourglass-end mr-1"></i>Next fetch {{
                  stream.next_scheduled_fetch }}
                </p>
                {% endif %} {% else %}
                <p class="text-gray-500 text-sm mt-2">
                  <i class="fas fa-pause-circle mr-1"></i>Scheduling disabled
                </p>
                {% endif %}
              </div>
              <div class="flex flex-col space-y-2">
                <button
                  class="edit-btn bg-yellow-500 text-white px-3 py-1 rounded text-sm hover:bg-yellow-600"
                  data-id="{{ stream.id }}"
                  data-hashtag="{{ stream.hashtag }}"
                  data-instance="{{ stream.instance }}"
                  data-active="{{ stream.active|lower }}"
                >
                  <i class="fas fa-edit mr-1"></i>Edit
                </button>
                <button
                  class="fetch-btn bg-green-500 text-white px-3 py-1 rounded text-sm hover:bg-green-600"
                  data-id="{{ stream.id }}"
                  data-hashtag="{{ stream.hashtag }}"
                >
                  <i class="fas fa-cloud-download-alt mr-1"></i>Fetch
                </button>
                <button
                  class="delete-btn bg-red-500 text-white px-3 py-1 rounded text-sm hover:bg-red-600"
                  data-id="{{ stream.id }}"
                  data-hashtag="{{ stream.hashtag }}"
                >
                  <i class="fas fa-trash mr-1"></i>Delete
                </button>
              </div>
            </div>
          </div>
          {% endfor %}
        </div>
        {% else %}
        <div class="text-center py-12">
          <i class="fas fa-hashtag text-4xl text-gray-300 mb-4"></i>
          <p class="text-gray-500">No streams configured yet.</p>
        </div>
        {% endif %}
      </div>
    </main>

    <!-- Edit Stream Modal -->
    <div
      id="editModal"
      class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50"
    >
      <div class="bg-white rounded-lg p-6 w-full max-w-md">
        <h3 class="text-xl font-bold text-gray-800 mb-4">Edit Stream</h3>
        <form id="editStreamForm">
          <input type="hidden" id="editStreamId" />
          <div class="mb-4">
            <label class="block text-gray-700 mb-2" for="editHashtag"
              >Hashtag</label
            >
            <input
              type="text"
              id="editHashtag"
              class="w-full px-4 py-2 border border-gray-300 rounded-lg bg-gray-100"
              readonly
            />
          </div>
          <div class="mb-4">
            <label class="block text-gray-700 mb-2" for="editInstance"
              >Instance</label
            >
            <input
              type="text"
              id="editInstance"
              class="w-full px-4 py-2 border border-gray-300 rounded-lg"
              required
            />
          </div>
          <div class="mb-4 flex items-center">
            <input type="checkbox" id="editActive" class="mr-2" />
            <label for="editActive" class="text-gray-700">Active</label>
          </div>
          <div class="mb-4">
            <label class="block text-gray-700 mb-2">Scheduling</label>
            <div class="space-y-3">
              <div class="flex items-center">
                <input type="checkbox" id="editEnableScheduling" class="mr-2" />
                <label for="editEnableScheduling" class="text-gray-700"
                  >Enable automatic fetching</label
                >
              </div>
              <div id="schedulingOptions" class="ml-6 space-y-2">
                <div>
                  <label
                    class="block text-gray-700 text-sm mb-1"
                    for="editFetchInterval"
                    >Fetch interval (minutes)</label
                  >
                  <input
                    type="number"
                    id="editFetchInterval"
                    class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm"
                    min="5"
                    max="1440"
                    value="60"
                  />
                  <p class="text-gray-500 text-xs mt-1">
                    Minimum: 5 minutes, Maximum: 24 hours (1440 minutes)
                  </p>
                </div>
                <div id="nextFetchInfo" class="text-sm text-blue-600 hidden">
                  <i class="fas fa-hourglass-end mr-1"></i
                  ><span id="nextFetchText"></span>
                </div>
              </div>
            </div>
          </div>
          <div class="flex justify-end space-x-4">
            <button
              type="button"
              id="cancelEditBtn"
              class="px-4 py-2 border border-gray-300 rounded-lg"
            >
              Cancel
            </button>
            <button
              type="submit"
              class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600"
            >
              Save Changes
            </button>
          </div>
        </form>
      </div>
    </div>

    <!-- Delete Stream Modal -->
    <div
      id="deleteModal"
      class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50"
    >
      <div class="bg-white rounded-lg p-6 w-full max-w-md">
        <h3 class="text-xl font-bold text-gray-800 mb-4">Delete Stream</h3>
        <p class="text-gray-600 mb-6">
          Are you sure you want to delete stream
          <span id="deleteHashtag" class="font-semibold"></span>? This action
          cannot be undone.
        </p>
        <div class="flex justify-end space-x-4">
          <button
            type="button"
            id="cancelDeleteBtn"
            class="px-4 py-2 border border-gray-300 rounded-lg"
          >
            Cancel
          </button>
          <button
            type="button"
            id="confirmDeleteBtn"
            class="px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600"
          >
            Delete
          </button>
        </div>
      </div>
    </div>

    <!-- Fetch Progress Modal -->
    <div
      id="fetchProgressModal"
      class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50"
    >
      <div class="bg-white rounded-lg p-6 w-full max-w-md">
        <h3 class="text-xl font-bold text-gray-800 mb-4">Fetching Streams</h3>
        <div class="mb-4">
          <p class="text-gray-600" id="fetchProgressText">Starting...</p>
          <div class="w-full bg-gray-200 rounded-full h-2.5 mt-2">
            <div
              id="fetchProgressBar"
              class="bg-blue-600 h-2.5 rounded-full"
              style="width: 0%"
            ></div>
          </div>
        </div>
        <div class="flex justify-end">
          <button
            type="button"
            id="cancelFetchBtn"
            class="px-4 py-2 border border-gray-300 rounded-lg"
          >
            Cancel
          </button>
        </div>
      </div>
    </div>

    <footer class="bg-gray-800 text-white mt-12">
      <div class="container mx-auto px-4 py-8">
        <div class="flex flex-col md:flex-row justify-between items-center">
          <div class="mb-6 md:mb-0">
            <div class="flex items-center mb-4">
              <div class="rounded-full p-2 bg-white/10 mr-4">
                <i class="fas fa-water"></i>
              </div>
              <div>
                <h2 class="text-xl font-bold">{{ app_name }}</h2>
                <p class="text-gray-300">Fediverse Content Stream Filtering</p>
              </div>
            </div>
            <p class="text-gray-400">
              Inspired by the ancient Dujiangyan irrigation system
            </p>
          </div>
          <div class="text-center md:text-right">
            <p class="text-gray-400">Version {{ app_version }}</p>
            <p class="text-gray-400">分流 - Divide the Flow</p>
          </div>
        </div>
      </div>
    </footer>

    <script>
      // Store API key from server context
      let apiKey = "{{ api_key }}";

      // Helper function to add API key to fetch headers
      function getHeaders(method = "GET", additionalHeaders = {}) {
        const headers = {
          "Content-Type": "application/json",
          ...additionalHeaders,
        };
        if (apiKey) {
          headers["X-API-Key"] = apiKey;
        }
        return headers;
      }

      // Add Stream Form
      document
        .getElementById("addStreamForm")
        .addEventListener("submit", async function (e) {
          e.preventDefault();
          const hashtag = document.getElementById("hashtag").value.trim();
          const instance = document.getElementById("instance").value.trim();
          const active = document.getElementById("active").checked;

          try {
            const response = await fetch("/api/v1/hashtags", {
              method: "POST",
              headers: getHeaders("POST"),
              body: JSON.stringify({
                hashtag: hashtag.replace("#", ""),
                instance: instance,
                active: active,
              }),
            });

            if (response.ok) {
              window.location.reload();
            } else {
              const error = await response.json();
              const errorMsg = error.detail || error.error || "Unknown error";
              showFlash("Error: " + errorMsg, "error");
            }
          } catch (error) {
            showFlash("Network error: " + error.message, "error");
          }
        });

      // Edit Stream Modal
      const editModal = document.getElementById("editModal");
      const editForm = document.getElementById("editStreamForm");
      const cancelEditBtn = document.getElementById("cancelEditBtn");
      let currentEditId = null;

      // Handle edit button clicks
      document.addEventListener("click", function (e) {
        if (
          e.target.classList.contains("edit-btn") ||
          e.target.closest(".edit-btn")
        ) {
          const btn = e.target.classList.contains("edit-btn")
            ? e.target
            : e.target.closest(".edit-btn");
          currentEditId = btn.dataset.id;
          document.getElementById("editStreamId").value = currentEditId;
          document.getElementById("editHashtag").value =
            "#" + btn.dataset.hashtag;
          document.getElementById("editInstance").value = btn.dataset.instance;
          document.getElementById("editActive").checked =
            btn.dataset.active === "true";

          // Load scheduling info from API
          fetch(`/api/v1/hashtags/${currentEditId}/schedule`, {
            headers: getHeaders("GET"),
          })
            .then((r) => r.json())
            .then((data) => {
              document.getElementById("editEnableScheduling").checked =
                data.enable_scheduling;
              document.getElementById("editFetchInterval").value =
                data.fetch_interval_minutes;

              // Show/hide scheduling options based on checkbox
              const schedulingOptions =
                document.getElementById("schedulingOptions");
              if (data.enable_scheduling) {
                schedulingOptions.classList.remove("hidden");
              } else {
                schedulingOptions.classList.add("hidden");
              }

              // Show next fetch time if available
              if (data.next_scheduled_fetch) {
                const nextFetchInfo = document.getElementById("nextFetchInfo");
                const nextFetchText = document.getElementById("nextFetchText");
                nextFetchText.textContent =
                  "Next fetch: " +
                  new Date(data.next_scheduled_fetch).toLocaleString();
                nextFetchInfo.classList.remove("hidden");
              }
            })
            .catch((err) => console.error("Error loading schedule:", err));

          editModal.classList.remove("hidden");
        }
      });

      // Toggle scheduling options visibility
      const enableSchedulingCheckbox = document.getElementById(
        "editEnableScheduling",
      );
      const schedulingOptions = document.getElementById("schedulingOptions");

      enableSchedulingCheckbox.addEventListener("change", function () {
        if (this.checked) {
          schedulingOptions.classList.remove("hidden");
        } else {
          schedulingOptions.classList.add("hidden");
        }
      });

      // Cancel edit
      cancelEditBtn.addEventListener("click", function () {
        editModal.classList.add("hidden");
        currentEditId = null;
      });

      // Submit edit form
      editForm.addEventListener("submit", async function (e) {
        e.preventDefault();
        if (!currentEditId) return;

        const instance = document.getElementById("editInstance").value.trim();
        const active = document.getElementById("editActive").checked;
        const enableScheduling = document.getElementById(
          "editEnableScheduling",
        ).checked;
        const fetchInterval = parseInt(
          document.getElementById("editFetchInterval").value,
        );

        try {
          // Update stream info
          const streamResponse = await fetch(
            `/api/v1/hashtags/${currentEditId}`,
            {
              method: "PATCH",
              headers: getHeaders("PATCH"),
              body: JSON.stringify({
                instance: instance,
                active: active,
              }),
            },
          );

          if (!streamResponse.ok) {
            const error = await streamResponse.json();
            const errorMsg = error.detail || error.error || "Unknown error";
            showFlash("Error updating stream: " + errorMsg, "error");
            return;
          }

          // Update schedule settings
          const scheduleResponse = await fetch(
            `/api/v1/hashtags/${currentEditId}/schedule`,
            {
              method: "PATCH",
              headers: getHeaders("PATCH"),
              body: JSON.stringify({
                enable_scheduling: enableScheduling,
                fetch_interval_minutes: fetchInterval,
              }),
            },
          );

          if (scheduleResponse.ok) {
            window.location.reload();
          } else {
            const error = await scheduleResponse.json();
            const errorMsg = error.detail || error.error || "Unknown error";
            showFlash("Error updating schedule: " + errorMsg, "error");
          }
        } catch (error) {
          showFlash("Network error: " + error.message, "error");
        }
      });

      // Delete Stream Modal
      const deleteModal = document.getElementById("deleteModal");
      const cancelDeleteBtn = document.getElementById("cancelDeleteBtn");
      const confirmDeleteBtn = document.getElementById("confirmDeleteBtn");
      let currentDeleteId = null;

      // Handle delete button clicks
      document.addEventListener("click", function (e) {
        if (
          e.target.classList.contains("delete-btn") ||
          e.target.closest(".delete-btn")
        ) {
          const btn = e.target.classList.contains("delete-btn")
            ? e.target
            : e.target.closest(".delete-btn");
          currentDeleteId = btn.dataset.id;
          document.getElementById("deleteHashtag").textContent =
            "#" + btn.dataset.hashtag;
          deleteModal.classList.remove("hidden");
        }
      });

      // Cancel delete
      cancelDeleteBtn.addEventListener("click", function () {
        deleteModal.classList.add("hidden");
        currentDeleteId = null;
      });

      // Confirm delete
      confirmDeleteBtn.addEventListener("click", async function () {
        if (!currentDeleteId) return;

        try {
          const response = await fetch(`/api/v1/hashtags/${currentDeleteId}`, {
            method: "DELETE",
            headers: getHeaders("DELETE"),
          });

          if (response.ok) {
            window.location.reload();
          } else {
            try {
              const error = await response.json();
              const errorMsg =
                error.detail || error.error || "Failed to delete stream";
              showFlash("Error: " + errorMsg, "error");
            } catch (parseError) {
              showFlash("Error: Failed to delete stream", "error");
            }
          }
        } catch (error) {
          showFlash("Network error: " + error.message, "error");
        }
      });

      // Fetch single stream
      document.addEventListener("click", async function (e) {
        if (
          e.target.classList.contains("fetch-btn") ||
          e.target.closest(".fetch-btn")
        ) {
          const btn = e.target.classList.contains("fetch-btn")
            ? e.target
            : e.target.closest(".fetch-btn");
          const streamId = btn.dataset.id;
          const hashtag = btn.dataset.hashtag;

          try {
            const response = await fetch(`/api/v1/hashtags/${streamId}/fetch`, {
              method: "POST",
              headers: getHeaders("POST"),
            });

            const result = await response.json();
            if (response.ok) {
              window.location.reload();
            } else {
              const errorMsg =
                result.detail ||
                result.error ||
                result.error_message ||
                "Unknown error";
              showFlash(`Error fetching #${hashtag}: ${errorMsg}`, "error");
            }
          } catch (error) {
            showFlash("Network error: " + error.message, "error");
          }
        }
      });

      // Fetch All Active Streams
      const fetchAllBtn = document.getElementById("fetchAllBtn");
      const fetchProgressModal = document.getElementById("fetchProgressModal");
      const fetchProgressText = document.getElementById("fetchProgressText");
      const fetchProgressBar = document.getElementById("fetchProgressBar");
      const cancelFetchBtn = document.getElementById("cancelFetchBtn");
      let isFetchingAll = false;
      let cancelFetch = false;

      fetchAllBtn.addEventListener("click", async function () {
        // Prevent multiple simultaneous fetches
        if (isFetchingAll) return;

        // Get all active streams
        const activeStreams = Array.from(
          document.querySelectorAll('.edit-btn[data-active="true"]'),
        );
        if (activeStreams.length === 0) {
          showFlash("No active streams to fetch.", "error");
          return;
        }

        // Disable button and show spinner
        const originalBtnHTML = fetchAllBtn.innerHTML;
        fetchAllBtn.disabled = true;
        fetchAllBtn.classList.add("opacity-50", "cursor-not-allowed");
        fetchAllBtn.innerHTML =
          '<i class="fas fa-spinner fa-spin mr-2"></i>Fetching...';

        isFetchingAll = true;
        cancelFetch = false;
        fetchProgressText.textContent = `Starting... (0/${activeStreams.length})`;
        fetchProgressBar.style.width = "0%";
        fetchProgressModal.classList.remove("hidden");

        let completed = 0;
        let totalPostsFetched = 0;
        let totalPostsSaved = 0;

        for (const btn of activeStreams) {
          if (cancelFetch) break;

          const streamId = btn.dataset.id;
          const hashtag = btn.dataset.hashtag;

          fetchProgressText.textContent = `Fetching #${hashtag}... (${completed}/${activeStreams.length})`;

          try {
            const response = await fetch(`/api/v1/hashtags/${streamId}/fetch`, {
              method: "POST",
              headers: getHeaders("POST"),
            });

            const result = await response.json();
            if (response.ok) {
              totalPostsFetched += result.posts_fetched;
              totalPostsSaved += result.posts_saved;
            } else {
              console.error(`Error fetching #${hashtag}:`, result);
            }
          } catch (error) {
            console.error(`Network error fetching #${hashtag}:`, error);
          }

          completed++;
          const progress = Math.round((completed / activeStreams.length) * 100);
          fetchProgressBar.style.width = `${progress}%`;
        }

        // Restore button state
        fetchAllBtn.disabled = false;
        fetchAllBtn.classList.remove("opacity-50", "cursor-not-allowed");
        fetchAllBtn.innerHTML = originalBtnHTML;

        if (cancelFetch) {
          fetchProgressText.textContent = "Fetch cancelled.";
          setTimeout(() => {
            fetchProgressModal.classList.add("hidden");
          }, 2000);
        } else {
          fetchProgressText.textContent = `Completed! Fetched ${totalPostsFetched} posts, saved ${totalPostsSaved} new posts.`;
          setTimeout(() => {
            fetchProgressModal.classList.add("hidden");
            window.location.reload();
          }, 2000);
        }

        isFetchingAll = false;
      });

      cancelFetchBtn.addEventListener("click", function () {
        if (isFetchingAll) {
          cancelFetch = true;
          fetchProgressText.textContent = "Cancelling...";
        }
      });

      // Close modals when clicking outside
      window.addEventListener("click", function (e) {
        if (e.target === editModal) {
          editModal.classList.add("hidden");
        }
        if (e.target === deleteModal) {
          deleteModal.classList.add("hidden");
        }
        if (e.target === fetchProgressModal && !isFetchingAll) {
          fetchProgressModal.classList.add("hidden");
        }
      });
      function showFlash(message, type) {
        const el = document.getElementById("flash");
        const colours =
          type === "error"
            ? "bg-red-100 border border-red-400 text-red-700"
            : "bg-green-100 border border-green-400 text-green-700";
        el.className = `${colours} px-4 py-3 rounded mb-4`;
        el.textContent = message;
        el.classList.remove("hidden");
        setTimeout(() => el.classList.add("hidden"), 4000);
      }
    </script>
  </body>
</html>
