// src/parser/luaParser.js

function stripInlineComments(s) {
  // entfernt "-- ..." aber nur, wenn wir nicht in Strings sind
  let out = "";
  let inStr = false;
  let quote = "";
  for (let i = 0; i < s.length; i++) {
    const ch = s[i];
    const next = s[i + 1];

    if (!inStr && (ch === "'" || ch === '"')) {
      inStr = true;
      quote = ch;
      out += ch;
      continue;
    }
    if (inStr && ch === quote && s[i - 1] !== "\\") {
      inStr = false;
      quote = "";
      out += ch;
      continue;
    }

    if (!inStr && ch === "-" && next === "-") {
      break;
    }
    out += ch;
  }
  return out.trim();
}

function splitTopLevel(str) {
  const parts = [];
  let depth = 0;
  let inStr = false;
  let quote = "";
  let current = "";

  for (let i = 0; i < str.length; i++) {
    const ch = str[i];
    const next = str[i + 1];

    if (!inStr && (ch === "'" || ch === '"')) {
      inStr = true;
      quote = ch;
      current += ch;
      continue;
    } else if (inStr && ch === quote && str[i - 1] !== "\\") {
      inStr = false;
      quote = "";
      current += ch;
      continue;
    }

    if (!inStr && ch === "-" && next === "-") {
      while (i < str.length && str[i] !== "\n") {
        i++;
      }
      continue;
    }

    if (!inStr) {
      if (ch === "{" || ch === "(") depth++;
      if (ch === "}" || ch === ")") depth--;
      if (ch === "," && depth === 0) {
        const t = current.trim();
        if (t) parts.push(t);
        current = "";
        continue;
      }
    }

    current += ch;
  }

  const t = current.trim();
  if (t) parts.push(t);
  return parts;
}

function parseLuaValue(valRaw) {
  const val = valRaw.trim();

  if (val === "nil") return null;
  if (val === "true") return true;
  if (val === "false") return false;

  // string
  if ((val.startsWith("'") && val.endsWith("'")) || (val.startsWith('"') && val.endsWith('"'))) {
    const inner = val.slice(1, -1);
    return inner.replace(/\\'/g, "'").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
  }

  // number
  if (/^-?\d+(\.\d+)?$/.test(val)) return Number(val);

  // vec3(...) oder vector3(...)
  if (/^vec3\s*\(/i.test(val) || /^vector3\s*\(/i.test(val)) {
    return val; // als String behalten
  }

  // table
  if (val.startsWith("{") && val.endsWith("}")) {
    return parseLuaTable(val.slice(1, -1));
  }

  // fallback (z.B. Identifier)
  return val;
}

// Rekursiv Table -> Object
function parseLuaTable(body) {
  const result = {};
  const clean = body.trim();

  const parts = splitTopLevel(clean);

  for (const p of parts) {
    const line = stripInlineComments(p);
    if (!line.includes("=")) continue;

    const eqIdx = line.indexOf("=");
    const rawKey = line.slice(0, eqIdx).trim();
    const rawVal = line.slice(eqIdx + 1).trim();

    // keys in Form ['key'] oder key
    let key = rawKey
      .replace(/^\[/, "")
      .replace(/\]$/, "")
      .replace(/^['"]/, "")
      .replace(/['"]$/, "")
      .trim();

    // manchmal kommen keys ohne [] daher (status = {...})
    key = key.replace(/[\s]/g, "");

    result[key] = parseLuaValue(rawVal);
  }

  return result;
}

function findRootTable(luaText) {
  // unterstützt:
  // ItemList = { ... }
  // QBShared.Items = { ... }
  const m = luaText.match(/(ItemList|QBShared\.Items)\s*=\s*{([\s\S]*)}\s*$/m);
  if (!m) return null;
  return { rootName: m[1], body: m[2] };
}

function findMatchingBrace(text, startIndex) {
  let depth = 0;
  let inStr = false;
  let quote = "";

  for (let i = startIndex; i < text.length; i++) {
    const ch = text[i];

    if (inStr) {
      if (ch === quote && text[i - 1] !== "\\") {
        inStr = false;
        quote = "";
      }
      continue;
    }

    if (ch === "'" || ch === '"') {
      inStr = true;
      quote = ch;
      continue;
    }

    if (ch === "{") depth++;
    if (ch === "}") depth--;

    if (depth === 0) return i;
  }

  return -1;
}

function extractTopLevelItems(text) {
  const items = [];
  let i = 0;

  while (i < text.length) {
    const ch = text[i];
    if (ch === "[" && (text[i + 1] === "'" || text[i + 1] === '"')) {
      const quote = text[i + 1];
      let j = i + 2;
      let id = "";
      while (j < text.length && text[j] !== quote) {
        id += text[j];
        j++;
      }
      if (j >= text.length || text[j + 1] !== "]") {
        i++;
        continue;
      }
      let k = j + 2;
      while (k < text.length && /\s/.test(text[k])) k++;
      if (text[k] !== "=") {
        i++;
        continue;
      }
      k++;
      while (k < text.length && /\s/.test(text[k])) k++;
      if (text[k] !== "{") {
        i++;
        continue;
      }

      const bodyStart = k;
      const bodyEnd = findMatchingBrace(text, bodyStart);
      if (bodyEnd === -1) {
        i = k + 1;
        continue;
      }

      items.push({
        id,
        body: text.slice(bodyStart + 1, bodyEnd),
        index: i,
      });
      i = bodyEnd + 1;
      continue;
    }
    i++;
  }

  return items;
}

export function parseLuaItems(luaText) {
  const root = findRootTable(luaText);
  if (!root) return [];

  const text = root.body;

  const items = [];
  const entries = extractTopLevelItems(text);
  for (const entry of entries) {
    const before = text.slice(Math.max(0, entry.index - 250), entry.index);
    const catMatch = before.match(/--\s*Category:\s*(.+)\s*$/im);
    const category = catMatch ? catMatch[1].trim() : "Nicht zugeordnet";
    const parsed = parseLuaTable(entry.body);
    items.push({
      id: entry.id,
      category,
      ...parsed,
    });
  }

  return items;
}

function serializeLua(val, indent = 6) {
  if (val === null) return "nil";
  if (typeof val === "boolean") return val ? "true" : "false";
  if (typeof val === "number") return String(val);

  if (typeof val === "string") {
    // vec3(...) / vector3(...) als raw lassen
    if (/^vec3\s*\(/i.test(val) || /^vector3\s*\(/i.test(val)) return val;
    return `'${val.replace(/'/g, "\\'")}'`;
  }

  if (Array.isArray(val)) {
    // wir nutzen Arrays selten – aber supporten sie
    return `{ ${val.map((v) => serializeLua(v, indent)).join(", ")} }`;
  }

  if (val && typeof val === "object") {
    let out = "{\n";
    for (const [k, v] of Object.entries(val)) {
      out += `${" ".repeat(indent)}['${k}'] = ${serializeLua(v, indent + 2)},\n`;
    }
    out += `${" ".repeat(indent - 2)}}`;
    return out;
  }

  return "nil";
}

export function buildLuaFromItems(items, rootName = "ItemList", options = {}) {
  const includeCategoryComments = options?.includeCategoryComments !== false;
  let lua = `${rootName} = {\n`;

  for (const item of items) {
    const { id, category, ...rest } = item;

    if (includeCategoryComments) {
      lua += `  -- Category: ${category || "Nicht zugeordnet"}\n`;
    }
    lua += `  ['${id}'] = ${serializeLua(rest, 6)},\n`;
  }

  lua += "}\n";
  return lua;
}
