import * as Blockly from 'blockly';
import { getToken, onAuthChange } from '../auth/client.js';

const BROWSER_STORAGE_KEY = 'esp32block_projects';

let workspace = null;
let captureOutput = null;
let writeFile = null;
let checkConnected = null;

let browserList;
let browserNameInput;
let browserSaveBtn, browserLoadBtn, browserMoveCloudBtn, browserDownloadBtn, browserDeleteBtn;
let browserUploadBtn, browserUploadInput;

let browserSelected = null;
let selectedEntry = null;
let cloudProjects = [];

export function initProjectsDialog(deps) {
  workspace = deps.workspace;
  captureOutput = deps.captureDeviceOutput;
  writeFile = deps.writeFileToDevice;
  checkConnected = deps.isConnected;

  browserList = document.getElementById('browser-list');
  browserNameInput = document.getElementById('browser-save-name');
  browserSaveBtn = document.getElementById('browser-save-btn');
  browserLoadBtn = document.getElementById('browser-load-btn');
  browserMoveCloudBtn = document.getElementById('browser-move-cloud-btn');
  browserDownloadBtn = document.getElementById('browser-download-btn');
  browserDeleteBtn = document.getElementById('browser-delete-btn');
  browserUploadBtn = document.getElementById('browser-upload-btn');
  browserUploadInput = document.getElementById('browser-upload-input');

  browserSaveBtn.addEventListener('click', saveBrowser);
  browserLoadBtn.addEventListener('click', loadBrowser);
  browserMoveCloudBtn.addEventListener('click', moveBrowserToCloud);
  browserDownloadBtn.addEventListener('click', downloadBrowser);
  browserDeleteBtn.addEventListener('click', deleteBrowser);
  browserUploadBtn.addEventListener('click', openUploadPicker);
  browserUploadInput.addEventListener('change', uploadFromComputer);

  onAuthChange(() => {
    refreshBrowserList().catch(() => { /* ignore */ });
  });
  refreshBrowserList().catch(() => { /* ignore */ });
}

export function refreshAll() {
  refreshBrowserList().catch(() => { /* ignore */ });
}

export async function saveCurrentWorkspaceToDevice(preferredName = 'main') {
  if (!workspace || !writeFile || !checkConnected || !checkConnected()) return null;
  const filename = preferredName.endsWith('.blk') ? preferredName : preferredName + '.blk';
  const state = Blockly.serialization.workspaces.save(workspace);
  const json = JSON.stringify(state);
  await writeFile(json, filename);
  return filename;
}

export async function loadWorkspaceFromDevice(preferredName = 'main') {
  if (!workspace || !captureOutput || !checkConnected || !checkConnected()) return null;
  const filename = preferredName.endsWith('.blk') ? preferredName : preferredName + '.blk';
  const raw = await captureOutput(
    `f=open('${filename}','r')\nprint(f.read(),end='')\nf.close()`
  );
  const state = JSON.parse(raw.trim());
  Blockly.serialization.workspaces.load(state, workspace);
  return filename;
}

// ─── Browser column ──────────────────────────────────────

function getBrowserProjects() {
  try {
    return JSON.parse(localStorage.getItem(BROWSER_STORAGE_KEY) || '{}');
  } catch { return {}; }
}

function setBrowserProjects(projects) {
  localStorage.setItem(BROWSER_STORAGE_KEY, JSON.stringify(projects));
}

async function fetchCloudProjects() {
  const token = getToken();
  if (!token) return [];
  const res = await fetch(apiUrl('/api/projects'), {
    headers: { Authorization: `Bearer ${token}` },
  });
  if (!res.ok) throw new Error(`Failed to fetch cloud projects (HTTP ${res.status})`);
  const data = await res.json();
  return Array.isArray(data?.projects) ? data.projects : [];
}

function apiUrl(path) {
  const base = import.meta.env.BASE_URL || '/';
  const p = path.startsWith('/') ? path.slice(1) : path;
  return (base.endsWith('/') ? base : base + '/') + p;
}

function displayName(entry) {
  const tag = entry.source === 'cloud' ? '[cloud]' : '[browser]';
  return `${entry.name} ${tag}`;
}

async function refreshBrowserList() {
  const loggedIn = !!getToken();
  const projects = getBrowserProjects();
  const names = Object.keys(projects).sort((a, b) => a.localeCompare(b));
  try {
    cloudProjects = await fetchCloudProjects();
  } catch {
    cloudProjects = [];
  }

  browserList.innerHTML = '';
  browserSelected = null; // legacy selection key
  selectedEntry = null;
  updateBrowserButtons();

  const entries = loggedIn
    ? [
      ...names.map((name) => ({ source: 'browser', name })),
      ...cloudProjects.map((p) => ({ source: 'cloud', name: p.name })),
    ]
    : names.map((name) => ({ source: 'browser', name }));

  entries.sort((a, b) => {
    const byName = a.name.localeCompare(b.name);
    if (byName !== 0) return byName;
    return a.source.localeCompare(b.source);
  });

  if (entries.length === 0) {
    browserList.innerHTML = '<li class="empty-msg">No saved projects</li>';
    return;
  }

  for (const entry of entries) {
    const li = document.createElement('li');
    li.textContent = displayName(entry);
    li.addEventListener('click', () => selectBrowserItem(entry, li));
    li.addEventListener('dblclick', () => { selectBrowserItem(entry, li); loadBrowser(); });
    browserList.appendChild(li);
  }
}

function selectBrowserItem(entry, li) {
  browserList.querySelectorAll('li').forEach(el => el.classList.remove('selected'));
  li.classList.add('selected');
  selectedEntry = entry;
  browserSelected = entry.name;
  browserNameInput.value = entry.name;
  updateBrowserButtons();
}

function updateBrowserButtons() {
  const hasSelection = !!selectedEntry;
  const canMoveToCloud = !!selectedEntry && selectedEntry.source === 'browser' && !!getToken();
  browserLoadBtn.disabled = !hasSelection;
  browserMoveCloudBtn.disabled = !canMoveToCloud;
  browserDownloadBtn.disabled = !hasSelection;
  browserDeleteBtn.disabled = !hasSelection;
}

async function saveCloud(name, state) {
  const token = getToken();
  if (!token) return false;
  const res = await fetch(apiUrl('/api/projects'), {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${token}`,
    },
    body: JSON.stringify({ name, state }),
  });
  return res.ok;
}

async function saveBrowser() {
  const name = browserNameInput.value.trim();
  if (!name) return;
  const state = Blockly.serialization.workspaces.save(workspace);
  if (getToken()) {
    await saveCloud(name, state).catch(() => { /* ignore */ });
  } else {
    const projects = getBrowserProjects();
    projects[name] = state;
    setBrowserProjects(projects);
  }
  browserNameInput.value = '';
  await refreshBrowserList();
}

async function loadBrowser() {
  if (!selectedEntry) return;
  if (selectedEntry.source === 'cloud') {
    const cloud = cloudProjects.find((p) => p.name === selectedEntry.name);
    if (!cloud?.state) return;
    Blockly.serialization.workspaces.load(cloud.state, workspace);
    return;
  }
  const projects = getBrowserProjects();
  const state = projects[selectedEntry.name];
  if (!state) return;
  Blockly.serialization.workspaces.load(state, workspace);
}

async function deleteCloud(name) {
  const token = getToken();
  if (!token) return false;
  const res = await fetch(apiUrl(`/api/projects/${encodeURIComponent(name)}`), {
    method: 'DELETE',
    headers: { Authorization: `Bearer ${token}` },
  });
  return res.ok;
}

async function deleteBrowser() {
  if (!selectedEntry) return;
  if (selectedEntry.source === 'cloud') {
    await deleteCloud(selectedEntry.name).catch(() => { /* ignore */ });
  } else {
    const projects = getBrowserProjects();
    delete projects[selectedEntry.name];
    setBrowserProjects(projects);
  }
  await refreshBrowserList();
}

async function moveBrowserToCloud() {
  if (!selectedEntry || selectedEntry.source !== 'browser' || !getToken()) return;
  const projects = getBrowserProjects();
  const state = projects[selectedEntry.name];
  if (!state) return;
  const ok = await saveCloud(selectedEntry.name, state).catch(() => false);
  if (!ok) return;
  delete projects[selectedEntry.name];
  setBrowserProjects(projects);
  await refreshBrowserList();
}

function downloadBrowser() {
  if (!selectedEntry) return;
  const state = selectedEntry.source === 'cloud'
    ? cloudProjects.find((p) => p.name === selectedEntry.name)?.state
    : getBrowserProjects()[selectedEntry.name];
  if (!state) return;
  const json = JSON.stringify(state, null, 2);
  const url = `data:application/json;charset=utf-8,${encodeURIComponent(json)}`;
  const a = document.createElement('a');
  a.href = url;
  a.download = `${selectedEntry.name}.blk`;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
}

function openUploadPicker() {
  if (!browserUploadInput) return;
  browserUploadInput.click();
}

async function uploadFromComputer(event) {
  const file = event?.target?.files?.[0];
  if (!file) return;
  try {
    const raw = await file.text();
    const parsed = JSON.parse(raw);
    if (!parsed || typeof parsed !== 'object') return;
    Blockly.serialization.workspaces.load(parsed, workspace);
  } catch {
    // ignore invalid file contents
  } finally {
    browserUploadInput.value = '';
  }
}
