(() => {
  const CLOSED_TABS_KEY = "closedTabs";
  const CLOSED_TABS_ENABLED_KEY = "closedTabsEnabled";
  const PASSWORD_UNMASK_ENABLED_KEY = "passwordUnmaskEnabled";
  const DRAG_FREE_ENABLED_KEY = "dragFreeEnabled";
  const MAX_RENDERED_ITEMS = 200;

  const queryInput = document.getElementById("query");
  const results = document.getElementById("results");
  const summary = document.getElementById("summary");
  const gmailStatus = document.getElementById("gmailStatus");
  const refreshGmailButton = document.getElementById("refreshGmail");
  const openGmailButton = document.getElementById("openGmail");
  const togglePasswordUnmaskButton = document.getElementById("togglePasswordUnmask");
  const toggleDragFreeButton = document.getElementById("toggleDragFree");
  const downloadStatus = document.getElementById("downloadStatus");
  const downloadUrlInput = document.getElementById("downloadUrl");
  const accelerateDownloadButton = document.getElementById("accelerateDownload");
  const refreshDownloadJobsButton = document.getElementById("refreshDownloadJobs");
  const openDownloadManagerButton = document.getElementById("openDownloadManager");
  const downloadJobs = document.getElementById("downloadJobs");
  const saveSingleFilePageButton = document.getElementById("saveSingleFilePage");

  let closedTabs = [];
  let closedTabsEnabled = true;
  let passwordUnmaskEnabled = false;
  let dragFreeEnabled = false;

  loadGmailStatus();
  loadPasswordUnmaskStatus();
  loadDragFreeStatus();
  loadClosedTabs();
  loadDownloadJobs();
  window.setInterval(loadDownloadJobs, 2500);

  queryInput.addEventListener("input", render);
  refreshGmailButton.addEventListener("click", () => loadGmailStatus(true));
  openGmailButton.addEventListener("click", () => {
    chrome.runtime.sendMessage({ type: "open-gmail" });
    window.close();
  });
  togglePasswordUnmaskButton.addEventListener("click", togglePasswordUnmask);
  toggleDragFreeButton.addEventListener("click", toggleDragFree);
  accelerateDownloadButton.addEventListener("click", accelerateDownloadUrl);
  refreshDownloadJobsButton.addEventListener("click", loadDownloadJobs);
  openDownloadManagerButton.addEventListener("click", openDownloadManager);
  downloadJobs.addEventListener("click", onDownloadJobClick);
  saveSingleFilePageButton.addEventListener("click", saveSingleFilePage);
  downloadUrlInput.addEventListener("keydown", (event) => {
    if (event.key === "Enter") {
      event.preventDefault();
      accelerateDownloadUrl();
    }
  });
  results.addEventListener("click", onResultClick);
  results.addEventListener("auxclick", onResultAuxClick);

  function accelerateDownloadUrl() {
    const url = normalizeDownloadUrl(downloadUrlInput.value);
    if (!url) {
      downloadStatus.textContent = "URL 오류";
      return;
    }

    downloadStatus.textContent = "전송 중...";
    chrome.runtime.sendMessage({ type: "accelerate-download-url", url }, (response) => {
      if (response?.ok) {
        downloadStatus.textContent = "시작 창 열림";
        downloadUrlInput.value = "";
        loadDownloadJobs();
        return;
      }

      downloadStatus.textContent = response?.error || "전송 실패";
    });
  }

  function normalizeDownloadUrl(value) {
    const trimmed = value.trim();
    if (!trimmed) {
      return "";
    }
    const withScheme = /^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;

    try {
      const url = new URL(withScheme);
      return ["http:", "https:"].includes(url.protocol) ? url.href : "";
    } catch (_) {
      return "";
    }
  }

  function loadDownloadJobs() {
    chrome.runtime.sendMessage({ type: "get-download-jobs" }, (response) => {
      if (chrome.runtime.lastError || !response?.ok) {
        downloadJobs.textContent = response?.error || chrome.runtime.lastError?.message || "브릿지 확인 실패";
        return;
      }

      renderDownloadJobs(response.jobs || []);
    });
  }

  function openDownloadManager() {
    chrome.runtime.sendMessage({ type: "open-download-manager" }, (response) => {
      if (chrome.runtime.lastError || !response?.ok) {
        downloadStatus.textContent = response?.error || chrome.runtime.lastError?.message || "관리자 열기 실패";
      }
    });
  }

  function renderDownloadJobs(jobs) {
    const visibleJobs = jobs.filter((job) => job.status !== "done").slice(0, 6);
    if (!visibleJobs.length) {
      downloadJobs.textContent = "큐 없음";
      return;
    }

    downloadJobs.replaceChildren(...visibleJobs.map(createDownloadJobItem));
  }

  function createDownloadJobItem(job) {
    const item = document.createElement("div");
    item.className = "download-job";
    item.dataset.id = job.id || "";

    const main = document.createElement("div");
    main.className = "download-job-main";

    const name = createTextElement(job.filename || fileNameFromPath(job.file) || job.url || "다운로드", "download-job-name");
    const meta = createTextElement(formatDownloadJobMeta(job), "download-job-meta");
    const progress = createDownloadJobProgress(job);
    main.append(name, meta, progress);

    const controls = document.createElement("div");
    controls.className = "download-job-controls";
    for (const action of getDownloadJobActions(job)) {
      const button = document.createElement("button");
      button.type = "button";
      button.dataset.action = action;
      button.textContent = getDownloadJobActionLabel(action);
      controls.append(button);
    }

    item.append(main, controls);
    return item;
  }

  function createDownloadJobProgress(job) {
    const total = Number(job.total || 0);
    const downloaded = Number(job.downloaded || 0);
    const percent = total > 0 ? Math.max(0, Math.min(100, Math.floor((downloaded / total) * 100))) : 0;
    const bar = document.createElement("div");
    bar.className = "download-job-progress";
    bar.title = total > 0 ? `${percent}%` : "크기 확인 중";
    const fill = document.createElement("span");
    fill.style.width = `${percent}%`;
    bar.append(fill);
    return bar;
  }

  function onDownloadJobClick(event) {
    const button = event.target.closest("button[data-action]");
    const item = event.target.closest(".download-job[data-id]");
    if (!button || !item?.dataset.id) {
      return;
    }

    button.disabled = true;
    chrome.runtime.sendMessage(
      { type: "control-download-job", jobId: item.dataset.id, action: button.dataset.action },
      (response) => {
        if (chrome.runtime.lastError || !response?.ok) {
          downloadStatus.textContent = response?.error || chrome.runtime.lastError?.message || "작업 실패";
        }
        loadDownloadJobs();
      }
    );
  }

  function getDownloadJobActions(job) {
    const status = job.status || "";
    if (job.queuedLocal) {
      return ["start", "remove"];
    }
    if (["running", "queued", "retrying", "pausing"].includes(status)) {
      return ["pause", "cancel"];
    }
    if (status === "paused") {
      return ["resume", "cancel"];
    }
    if (["failed", "cancelled"].includes(status)) {
      return ["retry", "clear"];
    }
    if (status === "done") {
      return ["clear"];
    }
    return ["clear"];
  }

  function getDownloadJobActionLabel(action) {
    return {
      pause: "일시정지",
      resume: "재개",
      retry: "재시도",
      cancel: "취소",
      clear: "삭제",
      start: "시작",
      remove: "제거"
    }[action] || action;
  }

  function formatDownloadJobMeta(job) {
    if (job.queuedLocal) {
      return job.saveDir ? `큐 · ${job.saveDir}` : "큐";
    }
    const status = {
      queued: "대기",
      running: "진행",
      retrying: "재시도",
      pausing: "정지 중",
      paused: "일시정지",
      cancelling: "취소 중",
      cancelled: "취소됨",
      done: "완료",
      failed: "실패"
    }[job.status] || job.status || "상태 없음";
    const downloaded = Number(job.downloaded || 0);
    const total = Number(job.total || 0);
    const progress = total > 0 ? ` · ${Math.floor((downloaded / total) * 100)}%` : "";
    const size = total > 0 ? ` · ${formatBytes(downloaded)} / ${formatBytes(total)}` : downloaded > 0 ? ` · ${formatBytes(downloaded)}` : "";
    const quality = job.qualityLabel ? ` · ${job.qualityLabel}` : "";
    const mode = job.mode === "accelerated"
      ? ` · ${Number(job.connections || 0) || 1}연결`
      : job.mode === "single"
        ? " · 단일 연결"
        : job.mode === "stream"
          ? " · 스트림 병합"
          : "";
    const error = job.error ? ` · ${job.error}` : "";
    return `${status}${progress}${size}${mode}${quality}${error}`;
  }

  function formatBytes(value) {
    const number = Number(value || 0);
    if (number >= 1024 * 1024 * 1024) {
      return `${(number / 1024 / 1024 / 1024).toFixed(1)}GB`;
    }
    if (number >= 1024 * 1024) {
      return `${(number / 1024 / 1024).toFixed(1)}MB`;
    }
    if (number >= 1024) {
      return `${(number / 1024).toFixed(1)}KB`;
    }
    return `${number}B`;
  }

  function fileNameFromPath(value) {
    return String(value || "").split(/[\\/]/).filter(Boolean).pop() || "";
  }

  function saveSingleFilePage() {
    saveSingleFilePageButton.textContent = "저장 중...";
    saveSingleFilePageButton.disabled = true;
    chrome.runtime.sendMessage({ type: "save-current-page-single-file" }, (response) => {
      saveSingleFilePageButton.disabled = false;
      if (chrome.runtime.lastError) {
        saveSingleFilePageButton.textContent = "저장 실패";
        resetSingleFileButtonText();
        return;
      }
      if (response?.ok) {
        saveSingleFilePageButton.textContent = response.filename ? "저장됨" : "접수됨";
        resetSingleFileButtonText();
        return;
      }

      saveSingleFilePageButton.textContent = response?.error || "저장 실패";
      resetSingleFileButtonText();
    });
  }

  function resetSingleFileButtonText() {
    window.setTimeout(() => {
      saveSingleFilePageButton.textContent = "페이지 저장";
    }, 1600);
  }

  function loadPasswordUnmaskStatus() {
    chrome.storage.sync.get({ [PASSWORD_UNMASK_ENABLED_KEY]: false }, (settings) => {
      passwordUnmaskEnabled = settings[PASSWORD_UNMASK_ENABLED_KEY] === true;
      renderPasswordUnmaskStatus();
    });
  }

  function togglePasswordUnmask() {
    passwordUnmaskEnabled = !passwordUnmaskEnabled;
    chrome.storage.sync.set({ [PASSWORD_UNMASK_ENABLED_KEY]: passwordUnmaskEnabled }, renderPasswordUnmaskStatus);
  }

  function renderPasswordUnmaskStatus() {
    togglePasswordUnmaskButton.classList.toggle("is-on", passwordUnmaskEnabled);
    togglePasswordUnmaskButton.setAttribute("aria-pressed", String(passwordUnmaskEnabled));
  }

  function loadDragFreeStatus() {
    chrome.storage.sync.get({ [DRAG_FREE_ENABLED_KEY]: false }, (settings) => {
      dragFreeEnabled = settings[DRAG_FREE_ENABLED_KEY] === true;
      renderDragFreeStatus();
    });
  }

  function toggleDragFree() {
    dragFreeEnabled = !dragFreeEnabled;
    chrome.storage.sync.set({ [DRAG_FREE_ENABLED_KEY]: dragFreeEnabled }, renderDragFreeStatus);
  }

  function renderDragFreeStatus() {
    toggleDragFreeButton.classList.toggle("is-on", dragFreeEnabled);
    toggleDragFreeButton.setAttribute("aria-pressed", String(dragFreeEnabled));
  }

  function loadGmailStatus(forceRefresh = false) {
    gmailStatus.textContent = "확인 중...";
    chrome.runtime.sendMessage(
      { type: forceRefresh ? "refresh-gmail-unread" : "get-gmail-unread" },
      (response) => {
        if (!response?.ok) {
          gmailStatus.textContent = response?.error || "확인 실패";
          return;
        }

        renderGmailStatus(response.data);
      }
    );
  }

  function renderGmailStatus(state) {
    if (!state?.enabled) {
      gmailStatus.textContent = "비활성화됨";
      return;
    }
    if (!state.ok) {
      gmailStatus.textContent = state.error || "확인 실패";
      return;
    }

    const source = state.source === "page" ? "탭 감지" : "피드 확인";
    gmailStatus.textContent = `안 읽음 ${state.unread}개 · ${source}`;
  }

  async function loadClosedTabs() {
    const settings = await chrome.storage.sync.get({ [CLOSED_TABS_ENABLED_KEY]: true });
    closedTabsEnabled = settings[CLOSED_TABS_ENABLED_KEY] !== false;
    if (!closedTabsEnabled) {
      closedTabs = [];
      render();
      return;
    }

    const result = await chrome.storage.local.get({ [CLOSED_TABS_KEY]: [] });
    closedTabs = Array.isArray(result[CLOSED_TABS_KEY]) ? result[CLOSED_TABS_KEY] : [];
    render();
    queryInput.focus();
  }

  async function onResultClick(event) {
    if (!closedTabsEnabled) {
      return;
    }

    const button = event.target.closest("button[data-action]");
    const item = event.target.closest("tr[data-id]");
    if (!item) {
      return;
    }

    const tab = closedTabs.find((entry) => entry.id === item.dataset.id);
    if (!tab) {
      return;
    }

    if (!button && event.target.closest(".record")) {
      await chrome.tabs.create({ url: tab.url });
      closedTabs = closedTabs.filter((entry) => entry.id !== tab.id);
      await chrome.storage.local.set({ [CLOSED_TABS_KEY]: closedTabs });
      window.close();
      return;
    }

    if (!button || button.dataset.action !== "delete") {
      return;
    }

    closedTabs = closedTabs.filter((entry) => entry.id !== tab.id);
    await chrome.storage.local.set({ [CLOSED_TABS_KEY]: closedTabs });
    render();
  }

  async function onResultAuxClick(event) {
    if (!closedTabsEnabled || event.button !== 1) {
      return;
    }

    const item = event.target.closest("tr[data-id]");
    if (!item || event.target.closest("button")) {
      return;
    }

    const tab = closedTabs.find((entry) => entry.id === item.dataset.id);
    if (!tab?.url) {
      return;
    }

    event.preventDefault();
    try {
      await navigator.clipboard.writeText(tab.url);
      summary.textContent = "링크 복사됨";
    } catch (_) {
      summary.textContent = "링크 복사 실패";
    }
  }

  function render() {
    if (!closedTabsEnabled) {
      results.replaceChildren();
      summary.textContent = "닫은 탭 저장/검색 기능이 비활성화되어 있습니다.";
      return;
    }

    const query = normalize(queryInput.value);
    const matchedTabs = query ? closedTabs.filter((tab) => matches(tab, query)) : closedTabs;
    const visibleTabs = matchedTabs.slice(0, MAX_RENDERED_ITEMS);

    results.replaceChildren(...visibleTabs.map(createResultItem));
    if (matchedTabs.length > MAX_RENDERED_ITEMS) {
      results.appendChild(createMoreItem(matchedTabs.length - MAX_RENDERED_ITEMS));
    }

    summary.textContent = closedTabs.length
      ? `${matchedTabs.length}개 표시 / 전체 ${closedTabs.length}개`
      : "저장된 닫은 탭이 없습니다.";
  }

  function createResultItem(tab) {
    const row = document.createElement("tr");
    row.dataset.id = tab.id;

    const contentCell = document.createElement("td");
    contentCell.className = "record";

    const topLine = document.createElement("div");
    topLine.className = "top-line";

    const title = createTextElement(tab.title || tab.url, "title");
    const meta = createTextElement(formatDate(tab.closedAt), "time");
    const url = createTextElement(tab.url, "url");
    const actionCell = document.createElement("td");
    actionCell.className = "actions";

    const deleteButton = document.createElement("button");
    deleteButton.type = "button";
    deleteButton.dataset.action = "delete";
    deleteButton.textContent = "삭제";

    actionCell.append(deleteButton);
    topLine.append(title, meta);
    contentCell.append(topLine, url);
    row.append(contentCell, actionCell);
    return row;
  }

  function createMoreItem(count) {
    const row = document.createElement("tr");
    const cell = document.createElement("td");
    cell.className = "more";
    cell.colSpan = 2;
    cell.textContent = `추가 ${count}개는 검색어를 더 입력하면 볼 수 있습니다.`;
    row.append(cell);
    return row;
  }

  function createTextElement(text, className) {
    const element = document.createElement("div");
    element.className = className;
    element.textContent = text;
    element.title = text;
    return element;
  }

  function matches(tab, query) {
    return normalize(`${tab.title || ""} ${tab.url || ""}`).includes(query);
  }

  function normalize(value) {
    return value.trim().toLocaleLowerCase("ko-KR");
  }

  function formatDate(value) {
    return new Intl.DateTimeFormat("ko-KR", {
      month: "2-digit",
      day: "2-digit",
      hour: "2-digit",
      minute: "2-digit"
    }).format(new Date(value));
  }
})();
