(() => {
  const STYLE_ID = "__tablinker_dcinside_style__";
  const REFRESH_STATUS_ID = "__tablinker_dcinside_refresh_status__";
  const HIDE_VERSION = "20260607-dcinside-hide-v1";
  const HOST_GALL_CLASS = "tablinker-dc-host-gall";
  const HOST_GALLOG_CLASS = "tablinker-dc-host-gallog";
  const FORCED_HIDE_SELECTORS_BY_HOST = {
    "gall.dcinside.com": [
      "#bottom_listwrap > section.right_content:nth-child(2)",
      "#top > footer.dcfoot.type1:last-child",
      "#top > div.gnb_bar:nth-child(2)",
      "#container > section.left_content:first-child > article:nth-child(2)"
    ],
    "gallog.dcinside.com": [
      "#container > article > div.conent_wrap.clear:last-child > div.wrap_right:last-child > footer.dcfoot:last-child"
    ]
  };
  const HIDE_STYLE_PROPERTIES = [
    ["display", "none"],
    ["visibility", "hidden"],
    ["height", "0"],
    ["min-height", "0"],
    ["max-height", "0"],
    ["margin", "0"],
    ["padding", "0"],
    ["border", "0"],
    ["overflow", "hidden"]
  ];
  const DEFAULT_SETTINGS = {
    dcCompactModeEnabled: false,
    dcAutoRefreshEnabled: true,
    dcAdaptiveRefreshEnabled: true,
    dcInPageNavigationEnabled: true,
    dcPauseRefreshDuringSearchEnabled: true,
    dcWriteLeaveGuardEnabled: true,
    dcWriteShortcutEnabled: true,
    dcRefreshMs: 5000
  };
  const MIN_REFRESH_MS = 2500;
  const MAX_REFRESH_MS = 60000;
  const MAX_ADAPTIVE_REFRESH_MS = 30000;

  let settings = { ...DEFAULT_SETTINGS };
  let knownPostIds = new Set();
  let refreshTimer = 0;
  let refreshIntervalMs = DEFAULT_SETTINGS.dcRefreshMs;
  let refreshing = false;
  let manualRefreshPaused = false;
  let submittingWriteForm = false;
  let hideObserver = null;
  let hideApplyTimer = 0;

  if (!isDcInsideHost()) {
    return;
  }

  bootstrapForcedHides();
  loadSettings();
  document.addEventListener("click", onDocumentClick, true);
  document.addEventListener("keydown", onDocumentKeyDown, true);
  window.addEventListener("popstate", () => {
    if (settings.dcInPageNavigationEnabled && isListPage()) {
      loadListPage(window.location.href, false);
    }
  });
  window.addEventListener("beforeunload", onBeforeUnload);
  chrome.storage.onChanged.addListener(onStorageChanged);

  function loadSettings() {
    chrome.storage.sync.get(DEFAULT_SETTINGS, (storedSettings) => {
      settings = normalizeSettings(storedSettings);
      applySettings();
    });
  }

  function onStorageChanged(changes, areaName) {
    if (areaName !== "sync") {
      return;
    }

    let changed = false;
    for (const key of Object.keys(DEFAULT_SETTINGS)) {
      if (changes[key]) {
        settings[key] = key === "dcRefreshMs"
          ? normalizeRefreshMs(changes[key].newValue)
          : changes[key].newValue !== false;
        changed = true;
      }
    }

    if (changed) {
      applySettings();
    }
  }

  function normalizeSettings(value) {
    return {
      ...DEFAULT_SETTINGS,
      ...value,
      dcRefreshMs: normalizeRefreshMs(value.dcRefreshMs)
    };
  }

  function normalizeRefreshMs(value) {
    const number = Number.parseInt(value, 10);
    if (!Number.isFinite(number)) {
      return DEFAULT_SETTINGS.dcRefreshMs;
    }

    return Math.min(MAX_REFRESH_MS, Math.max(MIN_REFRESH_MS, number));
  }

  function applySettings() {
    ensureStyle();
    document.documentElement?.classList.toggle("tablinker-dc-compact", settings.dcCompactModeEnabled);
    applyForcedHides();
    refreshIntervalMs = settings.dcRefreshMs;
    knownPostIds = collectPostIds();
    setupWriteFormSubmitGuard();
    scheduleRefresh();
    updateRefreshStatus();
  }

  function ensureStyle() {
    const styleText = getStyleText();
    let style = document.getElementById(STYLE_ID);
    if (!style) {
      const parent = getStyleParent();
      if (!parent) {
        return;
      }

      style = document.createElement("style");
      style.id = STYLE_ID;
      parent.appendChild(style);
    }

    if (style.dataset.oneDcinsideHideVersion !== HIDE_VERSION || style.textContent !== styleText) {
      style.dataset.oneDcinsideHideVersion = HIDE_VERSION;
      style.textContent = styleText;
    }
  }

  function getStyleText() {
    return `
      #${REFRESH_STATUS_ID} {
        display: inline-flex;
        align-items: center;
        margin-left: 8px;
        padding: 2px 7px;
        border: 1px solid #3b4890;
        background: #fff;
        color: #3b4890;
        font: 12px/1.4 Arial, sans-serif;
        cursor: pointer;
      }

      .tablinker-dc-new-post {
        animation: tablinkerDcNewPost 1.2s ease-out;
      }

      @keyframes tablinkerDcNewPost {
        0% { background: rgba(34, 197, 94, 0.35); }
        100% { background: transparent; }
      }

      html.${HOST_GALL_CLASS} #bottom_listwrap > section.right_content:nth-child(2),
      html.${HOST_GALL_CLASS} #top > footer.dcfoot.type1:last-child,
      html.${HOST_GALL_CLASS} #top > div.gnb_bar:nth-child(2),
      html.${HOST_GALL_CLASS} #container > section.left_content:first-child > article:nth-child(2),
      html.${HOST_GALLOG_CLASS} #container > article > div.conent_wrap.clear:last-child > div.wrap_right:last-child > footer.dcfoot:last-child {
        display: none !important;
        visibility: hidden !important;
        height: 0 !important;
        min-height: 0 !important;
        max-height: 0 !important;
        margin: 0 !important;
        padding: 0 !important;
        border: 0 !important;
        overflow: hidden !important;
      }

      html.tablinker-dc-compact .wrap_inner:has(.left_content .gall_listwrap.list) {
        width: auto;
        max-width: min(1050px, calc(100vw - 20px));
        margin-right: auto;
        margin-left: auto;
        box-sizing: border-box;
      }

      html.tablinker-dc-compact .left_content:has(.gall_listwrap.list) {
        width: 100%;
        max-width: 100%;
        box-sizing: border-box;
      }

      html.tablinker-dc-compact .left_content .gall_listwrap.list,
      html.tablinker-dc-compact .left_content .list_array_option,
      html.tablinker-dc-compact .left_content .bottom_array,
      html.tablinker-dc-compact .left_content .bottom_paging_wrap {
        max-width: 100%;
        box-sizing: border-box;
      }

      html.tablinker-dc-compact .left_content .gall_listwrap.list table {
        width: 100%;
        table-layout: fixed;
      }

      html.tablinker-dc-compact .left_content .gall_listwrap.list th,
      html.tablinker-dc-compact .left_content .gall_listwrap.list td {
        box-sizing: border-box;
      }

      html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_tit,
      html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_writer,
      html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_date,
      html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_count,
      html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_recommend {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }

      html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_tit a,
      html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_writer a,
      html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_writer span {
        display: inline-block;
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        vertical-align: middle;
      }

      html.tablinker-dc-compact .left_content .gall_listwrap.list col.gall_num,
      html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_num {
        width: 54px;
      }

      html.tablinker-dc-compact .left_content .gall_listwrap.list col.gall_writer,
      html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_writer {
        width: 96px;
      }

      html.tablinker-dc-compact .left_content .gall_listwrap.list col.gall_date,
      html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_date {
        width: 58px;
      }

      html.tablinker-dc-compact .left_content .gall_listwrap.list col.gall_count,
      html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_count,
      html.tablinker-dc-compact .left_content .gall_listwrap.list col.gall_recommend,
      html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_recommend {
        width: 44px;
      }

      @media (max-width: 1180px) {
        html.tablinker-dc-compact .wrap_inner:has(.left_content .gall_listwrap.list) > .right_content {
          display: none;
        }
      }

      @media (max-width: 760px) {
        html.tablinker-dc-compact .left_content .gall_listwrap.list col.gall_num,
        html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_num,
        html.tablinker-dc-compact .left_content .gall_listwrap.list col.gall_subject,
        html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_subject {
          display: none;
        }

        html.tablinker-dc-compact .left_content .gall_listwrap.list col.gall_writer,
        html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_writer {
          width: 78px;
        }

        html.tablinker-dc-compact .left_content .gall_listwrap.list col.gall_date,
        html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_date {
          width: 50px;
        }

        html.tablinker-dc-compact .left_content .gall_listwrap.list col.gall_count,
        html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_count,
        html.tablinker-dc-compact .left_content .gall_listwrap.list col.gall_recommend,
        html.tablinker-dc-compact .left_content .gall_listwrap.list .gall_recommend {
          width: 38px;
        }
      }

      @media (max-width: 560px) {
        html.tablinker-dc-compact .left_content .gall_listwrap.list th,
        html.tablinker-dc-compact .left_content .gall_listwrap.list td {
          padding-right: 2px;
          padding-left: 2px;
          font-size: 12px;
        }
      }
    `;
  }

  function getStyleParent() {
    return document.documentElement || document.head || document.body;
  }

  function bootstrapForcedHides() {
    applyForcedHides();
    if (document.readyState === "loading") {
      document.addEventListener("DOMContentLoaded", applyForcedHides, { once: true });
    } else {
      applyForcedHides();
    }
    window.addEventListener("load", applyForcedHides, { once: true });
    startForcedHideObserver();
  }

  function startForcedHideObserver() {
    if (hideObserver) {
      return;
    }

    hideObserver = new MutationObserver(queueApplyForcedHides);
    hideObserver.observe(document.documentElement || document, {
      childList: true,
      subtree: true
    });
  }

  function queueApplyForcedHides() {
    if (hideApplyTimer) {
      return;
    }

    hideApplyTimer = window.setTimeout(() => {
      hideApplyTimer = 0;
      applyForcedHides();
    }, 50);
  }

  function applyForcedHides() {
    ensureStyle();
    applyHostMarker();
    for (const selector of getForcedHideSelectors()) {
      for (const element of document.querySelectorAll(selector)) {
        hideElement(element);
      }
    }
  }

  function applyHostMarker() {
    const root = document.documentElement;
    if (!root) {
      return;
    }

    const hostname = getDcHostname();
    root.dataset.oneDcinsideHide = HIDE_VERSION;
    root.classList.toggle(HOST_GALL_CLASS, hostname === "gall.dcinside.com");
    root.classList.toggle(HOST_GALLOG_CLASS, hostname === "gallog.dcinside.com");
  }

  function getForcedHideSelectors() {
    return FORCED_HIDE_SELECTORS_BY_HOST[getDcHostname()] || [];
  }

  function hideElement(element) {
    if (element.dataset.oneDcinsideHidden === HIDE_VERSION) {
      return;
    }

    for (const [property, value] of HIDE_STYLE_PROPERTIES) {
      element.style.setProperty(property, value, "important");
    }
    element.dataset.oneDcinsideHidden = HIDE_VERSION;
  }

  function getDcHostname() {
    return window.location.hostname.toLowerCase();
  }

  function scheduleRefresh() {
    window.clearTimeout(refreshTimer);
    refreshTimer = 0;

    if (!settings.dcAutoRefreshEnabled || !isListPage() || manualRefreshPaused) {
      return;
    }

    refreshTimer = window.setTimeout(refreshCurrentList, refreshIntervalMs);
  }

  async function refreshCurrentList() {
    if (!settings.dcAutoRefreshEnabled || refreshing || document.hidden || shouldPauseForSearch()) {
      scheduleRefresh();
      updateRefreshStatus();
      return;
    }

    refreshing = true;
    try {
      const newCount = await fetchAndReplaceList(window.location.href, false, true);
      refreshIntervalMs = nextRefreshInterval(newCount, true);
    } catch (_) {
      refreshIntervalMs = nextRefreshInterval(0, false);
    } finally {
      refreshing = false;
      scheduleRefresh();
      updateRefreshStatus();
    }
  }

  function nextRefreshInterval(newCount, ok) {
    if (!settings.dcAdaptiveRefreshEnabled) {
      return settings.dcRefreshMs;
    }
    if (!ok) {
      return Math.min(MAX_ADAPTIVE_REFRESH_MS, Math.round(refreshIntervalMs * 1.5));
    }
    if (newCount >= 3) {
      return MIN_REFRESH_MS;
    }
    if (newCount > 0) {
      return Math.max(MIN_REFRESH_MS, settings.dcRefreshMs - newCount * 500);
    }

    return Math.min(MAX_ADAPTIVE_REFRESH_MS, Math.max(settings.dcRefreshMs, Math.round(refreshIntervalMs * 1.25)));
  }

  function shouldPauseForSearch() {
    if (!settings.dcPauseRefreshDuringSearchEnabled) {
      return false;
    }

    const params = new URLSearchParams(window.location.search);
    if (params.get("s_type") || params.get("s_keyword") || params.get("search_pos") || params.get("search")) {
      return true;
    }

    const searchInput = document.querySelector('input[name="s_keyword"], input[name="search_keyword"]');
    return Boolean(searchInput?.value?.trim());
  }

  async function loadListPage(url, pushState) {
    if (refreshing || !isListUrl(new URL(url, window.location.href))) {
      return;
    }

    refreshing = true;
    try {
      await fetchAndReplaceList(url, pushState, false);
      window.scrollTo({ top: 0, behavior: "auto" });
    } finally {
      refreshing = false;
      refreshIntervalMs = settings.dcRefreshMs;
      scheduleRefresh();
      updateRefreshStatus();
    }
  }

  async function fetchAndReplaceList(url, pushState, highlightNew) {
    const response = await fetch(url, {
      cache: "no-store",
      credentials: "include"
    });
    if (!response.ok) {
      throw new Error(`DCInside 응답 오류: ${response.status}`);
    }

    const text = await response.text();
    const newDocument = new DOMParser().parseFromString(text, "text/html");
    const oldPostIds = new Set(knownPostIds);

    replaceNode(".left_content .gall_listwrap.list", newDocument);
    replaceNode(".left_content .bottom_paging_wrap", newDocument);
    replaceNode(".left_content .list_array_option", newDocument);
    replaceNode(".left_content .bottom_array", newDocument);

    if (newDocument.title) {
      document.title = newDocument.title;
    }

    if (pushState) {
      history.pushState(null, "", url);
    }

    knownPostIds = collectPostIds();
    const newIds = [...knownPostIds].filter((id) => !oldPostIds.has(id));
    if (highlightNew) {
      highlightPosts(newIds);
    }

    ensureStyle();
    applyForcedHides();
    updateRefreshStatus();
    return newIds.length;
  }

  function replaceNode(selector, newDocument) {
    const current = document.querySelector(selector);
    const next = newDocument.querySelector(selector);
    if (current && next) {
      current.replaceWith(document.importNode(next, true));
    }
  }

  function collectPostIds() {
    return new Set(
      Array.from(document.querySelectorAll("tr.ub-content[data-no]"))
        .map((row) => row.dataset.no)
        .filter(Boolean)
    );
  }

  function highlightPosts(ids) {
    if (!ids.length) {
      return;
    }

    for (const id of ids) {
      document.querySelector(`tr.ub-content[data-no="${CSS.escape(id)}"]`)?.classList.add("tablinker-dc-new-post");
    }
  }

  function updateRefreshStatus() {
    if (!isListPage()) {
      document.getElementById(REFRESH_STATUS_ID)?.remove();
      return;
    }

    const target = document.querySelector(".left_content .list_array_option");
    if (!target) {
      document.getElementById(REFRESH_STATUS_ID)?.remove();
      return;
    }

    let status = document.getElementById(REFRESH_STATUS_ID);
    if (!status) {
      status = document.createElement("button");
      status.id = REFRESH_STATUS_ID;
      status.type = "button";
      status.addEventListener("click", () => {
        manualRefreshPaused = !manualRefreshPaused;
        scheduleRefresh();
        updateRefreshStatus();
      });
      target.appendChild(status);
    } else if (status.parentElement !== target) {
      target.appendChild(status);
    }

    if (!settings.dcAutoRefreshEnabled) {
      status.textContent = "새로고침: 꺼짐";
      return;
    }
    if (manualRefreshPaused) {
      status.textContent = "새로고침: 일시정지";
      return;
    }
    if (shouldPauseForSearch()) {
      status.textContent = "새로고침: 검색 중지";
      return;
    }

    status.textContent = `새로고침: ${(refreshIntervalMs / 1000).toFixed(1)}초`;
  }

  function onDocumentClick(event) {
    if (!settings.dcInPageNavigationEnabled || !isListPage()) {
      return;
    }

    const link = event.target.closest(".left_content .bottom_paging_box a[href]");
    if (!link) {
      return;
    }

    const url = new URL(link.href, window.location.href);
    if (!isListUrl(url)) {
      return;
    }

    event.preventDefault();
    loadListPage(url.href, true);
  }

  function onDocumentKeyDown(event) {
    const isWriteKey = event.code === "KeyW" || event.key === "w" || event.key === "W";
    if (!settings.dcWriteShortcutEnabled || !isWriteKey || event.ctrlKey || event.altKey || event.metaKey || event.isComposing) {
      return;
    }
    if (isEditable(event.target)) {
      return;
    }

    const writeUrl = getWriteUrl();
    if (!writeUrl) {
      return;
    }

    event.preventDefault();
    event.stopPropagation();
    window.location.href = writeUrl;
  }

  function setupWriteFormSubmitGuard() {
    const form = document.querySelector("form#write, form[name='write']");
    if (!form || form.dataset.tablinkerSubmitGuard === "true") {
      return;
    }

    form.dataset.tablinkerSubmitGuard = "true";
    form.addEventListener("submit", () => {
      submittingWriteForm = true;
    }, true);
  }

  function onBeforeUnload(event) {
    if (!settings.dcWriteLeaveGuardEnabled || !isWritePage() || submittingWriteForm || !hasWriteDraft()) {
      return;
    }

    event.preventDefault();
    event.returnValue = "";
  }

  function hasWriteDraft() {
    const subject = document.querySelector("#subject")?.value?.trim() || "";
    const memo = document.querySelector("#memo")?.value?.trim() || "";
    const editor = document.querySelector(".note-editable")?.textContent?.trim() || "";
    const fileSelected = Array.from(document.querySelectorAll('form#write input[type="file"]')).some((input) => input.files?.length);
    return Boolean(subject || memo || editor || fileSelected);
  }

  function getWriteUrl() {
    const url = new URL(window.location.href);
    const galleryId = url.searchParams.get("id");
    if (!galleryId || isWritePage()) {
      return "";
    }

    const pathPrefix = getBoardPathPrefix(url.pathname);
    if (!pathPrefix) {
      return "";
    }

    return `${url.origin}${pathPrefix}/write/?id=${encodeURIComponent(galleryId)}`;
  }

  function getBoardPathPrefix(pathname) {
    if (pathname.includes("/mgallery/board/")) {
      return "/mgallery/board";
    }
    if (pathname.includes("/mini/board/")) {
      return "/mini/board";
    }
    if (pathname.includes("/person/board/")) {
      return "/person/board";
    }
    if (pathname.includes("/board/")) {
      return "/board";
    }

    return "";
  }

  function isListPage() {
    return isListUrl(new URL(window.location.href));
  }

  function isListUrl(url) {
    return /\/(?:board|mgallery\/board|mini\/board|person\/board)\/lists\//.test(url.pathname);
  }

  function isWritePage() {
    return /\/(?:board|mgallery\/board|mini\/board|person\/board)\/write\//.test(window.location.pathname);
  }

  function isEditable(element) {
    return Boolean(
      element?.closest?.("input, textarea, select, [contenteditable='true'], [contenteditable='']")
    );
  }

  function isDcInsideHost() {
    return /(^|\.)dcinside\.com$/i.test(window.location.hostname);
  }
})();
