const DEFAULT_BLOCKLIST = ['youtube.com', 'tiktok.com', 'instagram.com', 'reddit.com', 'x.com'];
const DEFAULT_STATE = {
  focusActive: false,
  penaltyActive: false,
  penaltyUntil: 0,
  penaltyMessage: '',
  blocklist: DEFAULT_BLOCKLIST,
  taskLabel: '',
  updatedAt: 0,
};

function normalizeDomain(value) {
  return value
    .trim()
    .toLowerCase()
    .replace(/^https?:\/\//, '')
    .replace(/^www\./, '')
    .split('/')[0];
}

function isBlockedHost(hostname, blocklist) {
  const host = hostname.toLowerCase().replace(/^www\./, '');
  return blocklist.some((domain) => {
    const normalized = normalizeDomain(domain);
    return normalized && (host === normalized || host.endsWith(`.${normalized}`));
  });
}

function getState() {
  return chrome.storage.sync.get(DEFAULT_STATE);
}

function isPenaltyBlocking(state) {
  if (!state.penaltyActive) return false;
  if (!state.penaltyUntil) return true;
  return Date.now() < state.penaltyUntil;
}

function isBlockingActive(state) {
  return Boolean(state.focusActive) || isPenaltyBlocking(state);
}

function getEffectiveBlocklist(state) {
  const lists = [];
  if (state.focusActive && Array.isArray(state.blocklist)) {
    lists.push(...state.blocklist);
  }
  if (isPenaltyBlocking(state) && Array.isArray(state.penaltyBlocklist)) {
    lists.push(...state.penaltyBlocklist);
  }
  if (lists.length === 0 && isBlockingActive(state)) {
    return DEFAULT_BLOCKLIST;
  }
  return [...new Set(lists.map(normalizeDomain).filter(Boolean))];
}

async function setState(nextState) {
  const state = {
    ...nextState,
    blocklist: [...new Set((nextState.blocklist || DEFAULT_BLOCKLIST).map(normalizeDomain).filter(Boolean))],
    penaltyBlocklist: nextState.penaltyBlocklist
      ? [...new Set(nextState.penaltyBlocklist.map(normalizeDomain).filter(Boolean))]
      : nextState.penaltyBlocklist,
    updatedAt: Date.now(),
  };
  await chrome.storage.sync.set(state);
  await updateBadge();
  await redirectOpenBlockedTabs(state);
}

async function updateBadge() {
  const state = await getState();
  const blocking = isBlockingActive(state);
  await chrome.action.setBadgeText({ text: blocking ? 'ON' : '' });
  await chrome.action.setBadgeBackgroundColor({ color: isPenaltyBlocking(state) ? '#dc2626' : '#ef4444' });
}

function blockedPageUrl(originalUrl, mode) {
  return chrome.runtime.getURL(`blocked.html?url=${encodeURIComponent(originalUrl)}&mode=${mode || 'focus'}`);
}

async function redirectOpenBlockedTabs(state) {
  if (!isBlockingActive(state)) return;

  const blocklist = getEffectiveBlocklist(state);
  const tabs = await chrome.tabs.query({});
  await Promise.all(
    tabs.map(async (tab) => {
      if (!tab.id || !tab.url) return;

      let url;
      try {
        url = new URL(tab.url);
      } catch {
        return;
      }

      if (!['http:', 'https:'].includes(url.protocol)) return;
      if (url.hostname === 'localhost' || url.hostname === '127.0.0.1') return;
      if (!isBlockedHost(url.hostname, blocklist)) return;

      const mode = isPenaltyBlocking(state) ? 'penalty' : 'focus';
      await chrome.tabs.update(tab.id, { url: blockedPageUrl(tab.url, mode) });
    })
  );
}

chrome.runtime.onInstalled.addListener(async () => {
  const state = await getState();
  await setState(state);
});

chrome.runtime.onStartup.addListener(updateBadge);

chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
  if (!message || message.source !== 'goal-axis') return false;

  if (message.type === 'SET_FOCUS_STATE') {
    getState()
      .then((current) =>
        setState({
          ...current,
          focusActive: Boolean(message.focusActive),
          taskLabel: message.taskLabel || '',
          blocklist: Array.isArray(message.blocklist) ? message.blocklist : current.blocklist,
          penaltyActive: Boolean(message.penaltyActive),
          penaltyUntil: typeof message.penaltyUntil === 'number' ? message.penaltyUntil : current.penaltyUntil,
          penaltyMessage: message.penaltyMessage || current.penaltyMessage,
          penaltyBlocklist: Array.isArray(message.penaltyBlocklist) ? message.penaltyBlocklist : current.penaltyBlocklist,
        })
      )
      .then(() => sendResponse({ ok: true }))
      .catch((error) => sendResponse({ ok: false, error: String(error) }));
    return true;
  }

  if (message.type === 'GET_STATE') {
    getState()
      .then((state) => sendResponse({ ok: true, state }))
      .catch((error) => sendResponse({ ok: false, error: String(error) }));
    return true;
  }

  return false;
});

chrome.webNavigation.onBeforeNavigate.addListener(async (details) => {
  if (details.frameId !== 0) return;
  if (details.tabId < 0) return;

  let url;
  try {
    url = new URL(details.url);
  } catch {
    return;
  }

  if (!['http:', 'https:'].includes(url.protocol)) return;
  if (url.hostname === 'localhost' || url.hostname === '127.0.0.1') return;

  const state = await getState();
  if (!isBlockingActive(state)) return;

  const blocklist = getEffectiveBlocklist(state);
  if (!isBlockedHost(url.hostname, blocklist)) return;

  const mode = isPenaltyBlocking(state) ? 'penalty' : 'focus';
  chrome.tabs.update(details.tabId, { url: blockedPageUrl(details.url, mode) });
});
