import { loadSettings, saveDefinitionConfiguration, saveSettings } from "../shared/settings";
import { validateDefinitionConfiguration } from "../shared/site-definitions";
import type { FilterMode, Settings } from "../shared/types";
import "./style.css";

const form = document.querySelector<HTMLFormElement>("#settings");
const threshold = document.querySelector<HTMLInputElement>("#threshold");
const thresholdValue = document.querySelector<HTMLElement>("#threshold-value");
const mode = document.querySelector<HTMLSelectElement>("#filter-mode");
const showScore = document.querySelector<HTMLInputElement>("#show-score");
const status = document.querySelector<HTMLElement>("#status");
const definitions = document.querySelector<HTMLTextAreaElement>("#definitions");
const importButton = document.querySelector<HTMLButtonElement>("#import-definitions");
const exportButton = document.querySelector<HTMLButtonElement>("#export-definitions");
const definitionFile = document.querySelector<HTMLInputElement>("#definition-file");
const subscriptionUrl = document.querySelector<HTMLInputElement>("#subscription-url");
const subscriptionList = document.querySelector<HTMLElement>("#subscriptions");
const addSubscriptionButton = document.querySelector<HTMLButtonElement>("#add-subscription");
const refreshSubscriptionsButton = document.querySelector<HTMLButtonElement>("#refresh-subscriptions");
let currentSettings: Settings;

void loadSettings().then((settings) => {
  currentSettings = settings;
  threshold!.value = String(settings.threshold);
  mode!.value = settings.filterMode;
  showScore!.checked = settings.showScore;
  definitions!.value = JSON.stringify(definitionConfiguration(settings), null, 2);
  renderSubscriptions(settings);
  updateThresholdLabel();
});

addSubscriptionButton?.addEventListener("click", async () => {
  const url = subscriptionUrl?.value.trim();
  if (!url) return;
  try {
    const parsed = new URL(url);
    if (!/^https?:$/.test(parsed.protocol)) throw new Error("Subscriptions must use HTTP or HTTPS.");
    const id = `custom-${Date.now().toString(36)}`;
    currentSettings = await saveSettings({ subscriptions: [...currentSettings.subscriptions, { id, name: url, url, enabled: true, priority: currentSettings.subscriptions.length }] });
    subscriptionUrl!.value = "";
    renderSubscriptions(currentSettings);
    showStatus("Subscription added. Use Update subscriptions now to fetch it.");
  } catch (error) { showStatus(error instanceof Error ? error.message : String(error), true); }
});

refreshSubscriptionsButton?.addEventListener("click", async () => {
  try {
    const response = await chrome.runtime.sendMessage({ type: "REFRESH_SUBSCRIPTIONS" });
    if (!response) throw new Error("The background page did not respond. Reload the extension and try again.");
    if (response?.error) throw new Error(response.error);
    currentSettings = response.settings;
    renderSubscriptions(currentSettings);
    showStatus("Subscriptions updated.");
  } catch (error) { showStatus(error instanceof Error ? error.message : String(error), true); }
});

threshold?.addEventListener("input", updateThresholdLabel);
form?.addEventListener("submit", async (event) => {
  event.preventDefault();
  try {
    const configuration = parseDefinitionConfiguration();
    await saveDefinitionConfiguration(configuration);
    await saveSettings({ threshold: Number(threshold?.value), filterMode: mode?.value as FilterMode, showScore: showScore?.checked });
    showStatus("Saved. Reload matching pages to apply definition changes.");
  } catch (error) { showStatus(error instanceof Error ? error.message : String(error), true); }
});


importButton?.addEventListener("click", () => definitionFile?.click());
definitionFile?.addEventListener("change", async () => {
  const file = definitionFile.files?.[0];
  if (!file) return;
  try {
    const parsed = JSON.parse(await file.text()) as unknown;
    const validation = validateDefinitionConfiguration(parsed);
    if (!validation.valid) throw new Error(validation.errors.join("\n"));
    if (definitions) definitions.value = JSON.stringify(validation.value, null, 2);
    showStatus("Definition JSON imported. Save to apply it.");
  } catch (error) { showStatus(error instanceof Error ? error.message : String(error), true); }
  definitionFile.value = "";
});

exportButton?.addEventListener("click", () => {
  try {
    const blob = new Blob([JSON.stringify(parseDefinitionConfiguration(), null, 2)], { type: "application/json" });
    const url = URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.href = url;
    link.download = "vibeguard-definitions.json";
    link.click();
    URL.revokeObjectURL(url);
  } catch (error) { showStatus(error instanceof Error ? error.message : String(error), true); }
});

function updateThresholdLabel(): void {
  if (thresholdValue && threshold) thresholdValue.textContent = `${Math.round(Number(threshold.value) * 100)}%`;
}

function definitionConfiguration(settings?: Settings): { customDefinitions: Settings["customDefinitions"]; disabledDefinitionIds: string[]; subscriptions: Settings["subscriptions"]; subscriptionCollections: Settings["subscriptionCollections"] } {
  return { customDefinitions: settings?.customDefinitions ?? [], disabledDefinitionIds: settings?.disabledDefinitionIds ?? [], subscriptions: settings?.subscriptions ?? [], subscriptionCollections: settings?.subscriptionCollections ?? [] };
}

function parseDefinitionConfiguration(): { customDefinitions: Settings["customDefinitions"]; disabledDefinitionIds: string[]; subscriptions: Settings["subscriptions"]; subscriptionCollections: Settings["subscriptionCollections"] } {
  let parsed: unknown;
  try { parsed = JSON.parse(definitions?.value ?? "{}"); } catch { throw new Error("Definition JSON is invalid."); }
  const validation = validateDefinitionConfiguration(parsed);
  if (!validation.valid) throw new Error(validation.errors.join("\n"));
  return validation.value;
}

function renderSubscriptions(settings: Settings): void {
  if (!subscriptionList) return;
  subscriptionList.replaceChildren(...[...settings.subscriptions].sort((a, b) => a.priority - b.priority).map((subscription) => {
    const row = document.createElement("div");
    row.className = "box p-3";
    const title = document.createElement("strong");
    title.textContent = `${subscription.name} (${subscription.enabled ? "enabled" : "disabled"})`;
    const detail = document.createElement("small");
    detail.textContent = ` ${subscription.url} — ${subscription.lastError ?? (subscription.lastSuccessfulUpdate ? `updated ${new Date(subscription.lastSuccessfulUpdate).toLocaleString()}` : "not updated yet")}`;
    const toggle = document.createElement("input");
    toggle.type = "checkbox";
    toggle.checked = subscription.enabled;
    toggle.className = "mr-2";
    toggle.addEventListener("change", async () => {
      currentSettings = await saveSettings({ subscriptions: currentSettings.subscriptions.map((item) => item.id === subscription.id ? { ...item, enabled: toggle.checked } : item) });
      renderSubscriptions(currentSettings);
    });
    const remove = document.createElement("button");
    remove.type = "button";
    remove.className = "button is-small is-light ml-2";
    remove.textContent = "Remove";
    remove.addEventListener("click", async () => {
      currentSettings = await saveSettings({ subscriptions: currentSettings.subscriptions.filter((item) => item.id !== subscription.id), subscriptionCollections: currentSettings.subscriptionCollections.filter((item) => item.collectionId !== subscription.id) });
      renderSubscriptions(currentSettings);
    });
    const raise = document.createElement("button");
    raise.type = "button";
    raise.className = "button is-small is-light ml-1";
    raise.textContent = "↑";
    raise.title = "Increase priority";
    raise.addEventListener("click", () => void moveSubscription(subscription.id, -1));
    const lower = document.createElement("button");
    lower.type = "button";
    lower.className = "button is-small is-light ml-1";
    lower.textContent = "↓";
    lower.title = "Decrease priority";
    lower.addEventListener("click", () => void moveSubscription(subscription.id, 1));
    row.prepend(toggle);
    row.append(title, document.createElement("br"), detail, remove, raise, lower);
    return row;
  }));
}

async function moveSubscription(id: string, direction: -1 | 1): Promise<void> {
  const ordered = [...currentSettings.subscriptions].sort((a, b) => a.priority - b.priority);
  const index = ordered.findIndex((subscription) => subscription.id === id);
  const swapIndex = index + direction;
  if (index < 0 || swapIndex < 0 || swapIndex >= ordered.length) return;
  const currentPriority = ordered[index]!.priority;
  ordered[index]!.priority = ordered[swapIndex]!.priority;
  ordered[swapIndex]!.priority = currentPriority;
  currentSettings = await saveSettings({ subscriptions: ordered });
  renderSubscriptions(currentSettings);
}

function showStatus(message: string, isError = false): void {
  if (!status) return;
  status.textContent = message;
  status.style.color = isError ? "#b42318" : "";
}
