const form = document.getElementById('createForm');
const nodeEl = document.getElementById('node');
const storageEl = document.getElementById('storage');
const templateEl = document.getElementById('template');
const vmidEl = document.getElementById('vmid');
const ipModeEl = document.getElementById('ip_mode');
const refreshVmidBtn = document.getElementById('refreshVmid');
const submitBtn = document.getElementById('submitBtn');
const taskProgressBar = document.getElementById('taskProgressBar');
const taskStage = document.getElementById('taskStage');
const taskLogs = document.getElementById('taskLogs');
const containerDetails = document.getElementById('containerDetails');
const globalAlert = document.getElementById('globalAlert');

let taskPollTimer = null;

function showAlert(message, level = 'danger') {
  globalAlert.innerHTML = `<div class="alert alert-${level} py-2">${message}</div>`;
}

function clearAlert() {
  globalAlert.innerHTML = '';
}

function setFieldError(name, message = '') {
  const target = document.querySelector(`[data-error-for="${name}"]`);
  const field = form.querySelector(`[name="${name}"]`);
  if (target) target.textContent = message || '';
  if (field) field.classList.toggle('is-invalid', Boolean(message));
}

function clearErrors() {
  form.querySelectorAll('.is-invalid').forEach((el) => el.classList.remove('is-invalid'));
  form.querySelectorAll('[data-error-for]').forEach((el) => {
    el.textContent = '';
  });
}

async function parseResponse(response, url) {
  const text = await response.text();

  let data;
  try {
    data = JSON.parse(text);
  } catch (e) {
    throw new Error(`Server nevrátil JSON pro ${url}.`);
  }

  return data;
}

async function apiGet(url) {
  const response = await fetch(url, {
    credentials: 'same-origin',
  });

  const data = await parseResponse(response, url);

  if (!response.ok || data.success === false) {
    throw new Error(data.error || `HTTP ${response.status}`);
  }

  return data;
}

async function apiPost(url, payload) {
  const response = await fetch(url, {
    method: 'POST',
    credentials: 'same-origin',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
  });

  const data = await parseResponse(response, url);

  if (!response.ok || data.success === false) {
    throw new Error(data.error || `HTTP ${response.status}`);
  }

  return data;
}

function option(text, value) {
  const opt = document.createElement('option');
  opt.value = value;
  opt.textContent = text;
  return opt;
}

async function loadNodes() {
  const data = await apiGet('/api/nodes');
  nodeEl.innerHTML = '';

  data.nodes.forEach((node) => {
    nodeEl.appendChild(option(node, node));
  });

  if (window.APP_DEFAULTS?.defaultNode && data.nodes.includes(window.APP_DEFAULTS.defaultNode)) {
    nodeEl.value = window.APP_DEFAULTS.defaultNode;
  }
}

async function loadStorage() {
  if (!nodeEl.value) {
    storageEl.innerHTML = '';
    return;
  }

  const data = await apiGet(`/api/storage/${encodeURIComponent(nodeEl.value)}`);
  storageEl.innerHTML = '';

  data.storage.forEach((item) => {
    storageEl.appendChild(option(item, item));
  });

  if (window.APP_DEFAULTS?.defaultStorage && data.storage.includes(window.APP_DEFAULTS.defaultStorage)) {
    storageEl.value = window.APP_DEFAULTS.defaultStorage;
  }
}

async function loadTemplates() {
  templateEl.innerHTML = '';

  if (!nodeEl.value || !storageEl.value) {
    return;
  }

  const data = await apiGet(
    `/api/templates/${encodeURIComponent(nodeEl.value)}/${encodeURIComponent(storageEl.value)}`
  );

  data.templates.forEach((item) => {
    templateEl.appendChild(option(item, item));
  });
}

async function loadNextId() {
  const data = await apiGet('/api/next-vmid');
  vmidEl.value = data.vmid;
}

function toggleStaticIpFields() {
  const staticOnly = document.querySelectorAll('.static-ip-only');
  const isStatic = ipModeEl.value === 'static';
  staticOnly.forEach((el) => el.classList.toggle('d-none', !isStatic));
}

function collectFormData() {
  return {
    node: nodeEl.value,
    storage: storageEl.value,
    template: templateEl.value,
    vmid: vmidEl.value,
    hostname: document.getElementById('hostname').value,
    bridge: document.getElementById('bridge').value,
    cores: document.getElementById('cores').value,
    memory: document.getElementById('memory').value,
    disk: document.getElementById('disk_gb').value,
    ip_mode: document.getElementById('ip_mode').value,
    ip_last_octet: document.getElementById('ip_host').value,
    vlan: document.getElementById('vlan_tag').value,
    gateway: document.getElementById('gateway').value,
    nameserver: document.getElementById('dns').value,
    searchdomain: document.getElementById('searchdomain').value,
    password: document.getElementById('password').value,
    start_on_boot: document.getElementById('onboot').checked,
    start_now: document.getElementById('start_now').checked,
    unprivileged: document.getElementById('unprivileged').checked,
    enable_nesting: document.getElementById('enable_nesting').checked,
  };
}

function renderContainerDetails(container) {
  containerDetails.innerHTML = `
    <dl class="row small mb-0">
      <dt class="col-5">Hostname</dt><dd class="col-7">${container.hostname || '-'}</dd>
      <dt class="col-5">VMID</dt><dd class="col-7">${container.vmid || '-'}</dd>
      <dt class="col-5">Node</dt><dd class="col-7">${container.node || '-'}</dd>
      <dt class="col-5">Stav</dt><dd class="col-7">${container.status || '-'}</dd>
      <dt class="col-5">CPU</dt><dd class="col-7">${container.cores || '-'}</dd>
      <dt class="col-5">RAM</dt><dd class="col-7">${container.memory || '-'} MB</dd>
      <dt class="col-5">RootFS</dt><dd class="col-7 text-break">${container.rootfs || '-'}</dd>
      <dt class="col-5">Síť</dt><dd class="col-7 text-break">${container.net0 || '-'}</dd>
      <dt class="col-5">DNS</dt><dd class="col-7">${container.nameserver || '-'}</dd>
      <dt class="col-5">Search domain</dt><dd class="col-7">${container.searchdomain || '-'}</dd>
      <dt class="col-5">Template</dt><dd class="col-7 text-break">${container.ostemplate || '-'}</dd>
    </dl>
  `;
}

function updateProgress(progress, text, logs = [], variant = 'primary') {
  taskProgressBar.style.width = `${progress}%`;
  taskProgressBar.textContent = `${progress}%`;
  taskProgressBar.className = `progress-bar ${progress < 100 ? 'progress-bar-striped progress-bar-animated' : ''} bg-${variant}`.trim();
  taskStage.textContent = text;
  taskLogs.textContent = logs.length ? logs.join('\n') : '-';
}

function stopPolling() {
  if (taskPollTimer) {
    clearTimeout(taskPollTimer);
    taskPollTimer = null;
  }
}

async function loadContainerDetails(node, vmid) {
  const data = await apiGet(`/api/container-details/${encodeURIComponent(node)}/${encodeURIComponent(vmid)}`);
  if (data.details) {
    renderContainerDetails(data.details);
  }
}

async function startContainerNow(node, vmid) {
  return apiPost('/api/start-lxc', { node, vmid });
}

async function pollTask(node, upid) {
  const data = await apiGet(
    `/api/task-status?node=${encodeURIComponent(node)}&upid=${encodeURIComponent(upid)}`
  );

  const failed = !data.running && data.exitstatus && data.exitstatus !== 'OK';

  let stageText = 'Úloha běží...';
  if (!data.running && data.exitstatus === 'OK') {
    stageText = 'Úloha byla úspěšně dokončena.';
  } else if (!data.running && data.exitstatus && data.exitstatus !== 'OK') {
    stageText = `Úloha skončila chybou: ${data.exitstatus}`;
  }

  updateProgress(
    data.progress ?? 0,
    stageText,
    data.logs || [],
    failed ? 'danger' : (data.progress === 100 && data.exitstatus === 'OK' ? 'success' : 'primary')
  );

  return data;
}

async function waitForTask(node, upid) {
  while (true) {
    const data = await pollTask(node, upid);

    if (!data.running) {
      return data;
    }

    await new Promise((resolve) => {
      taskPollTimer = setTimeout(resolve, 2000);
    });
  }
}

nodeEl.addEventListener('change', async () => {
  clearAlert();
  try {
    await loadStorage();
    await loadTemplates();
  } catch (error) {
    showAlert(error.message);
  }
});

storageEl.addEventListener('change', async () => {
  clearAlert();
  try {
    await loadTemplates();
  } catch (error) {
    showAlert(error.message);
  }
});

ipModeEl.addEventListener('change', toggleStaticIpFields);

refreshVmidBtn.addEventListener('click', async () => {
  try {
    await loadNextId();
  } catch (error) {
    showAlert(error.message);
  }
});

form.addEventListener('reset', () => {
  stopPolling();
  clearErrors();
  clearAlert();

  setTimeout(() => {
    toggleStaticIpFields();
    updateProgress(0, 'Ještě nebyla spuštěna žádná úloha.', []);
    containerDetails.textContent = 'Po úspěšném vytvoření se tady zobrazí detaily.';
  }, 0);
});

form.addEventListener('submit', async (event) => {
  event.preventDefault();
  stopPolling();
  clearErrors();
  clearAlert();
  submitBtn.disabled = true;
  containerDetails.textContent = 'Čekám na dokončení vytváření kontejneru.';
  updateProgress(8, 'Odesílám požadavek do Proxmoxu...', []);

  try {
    const payload = collectFormData();
    const startNow = payload.start_now;

    const createData = await apiPost('/api/create-lxc', payload);

    showAlert(`Úloha byla spuštěna. VMID ${createData.vmid}, hostname ${createData.hostname}.`, 'info');
    updateProgress(12, 'Vytváření kontejneru bylo přijato Proxmoxem.', []);

    const createTaskResult = await waitForTask(createData.node, createData.upid);

    if (createTaskResult.exitstatus !== 'OK') {
      submitBtn.disabled = false;
      showAlert(`Vytvoření kontejneru selhalo: ${createTaskResult.exitstatus || 'neznámá chyba'}`, 'danger');
      return;
    }

    if (startNow) {
      updateProgress(90, 'Spouštím nově vytvořený kontejner...', createTaskResult.logs || []);
      const startData = await startContainerNow(createData.node, createData.vmid);
      const startTaskResult = await waitForTask(startData.node, startData.upid);

      if (startTaskResult.exitstatus !== 'OK') {
        submitBtn.disabled = false;
        showAlert(`Kontejner byl vytvořen, ale nepodařilo se ho spustit: ${startTaskResult.exitstatus || 'neznámá chyba'}`, 'warning');
        await loadContainerDetails(createData.node, createData.vmid);
        return;
      }
    }

    updateProgress(100, 'Kontejner byl úspěšně vytvořen.', [], 'success');
    showAlert(`Kontejner VMID ${createData.vmid} byl úspěšně vytvořen.`, 'success');
    await loadContainerDetails(createData.node, createData.vmid);
    submitBtn.disabled = false;
  } catch (error) {
    submitBtn.disabled = false;
    showAlert(error.message);
    updateProgress(100, `Požadavek selhal: ${error.message}`, [], 'danger');
  }
});

(async function init() {
  toggleStaticIpFields();

  try {
    await loadNodes();
    await loadStorage();
    await loadTemplates();
    await loadNextId();
  } catch (error) {
    showAlert(error.message);
  }
})();
