const { app, BrowserWindow, ipcMain, dialog } = require("electron");
const path = require("path");
const fs = require("fs");
const { spawn } = require("child_process");
const https = require("https");

let mainWindow;

// --- Settings & Project Path ---

function getSettingsPath() {
  return path.join(app.getPath("userData"), "settings.json");
}

function loadProjectPath() {
  const settingsFile = getSettingsPath();
  if (fs.existsSync(settingsFile)) {
    try {
      const s = JSON.parse(fs.readFileSync(settingsFile, "utf-8"));
      if (s.projectPath && fs.existsSync(path.join(s.projectPath, "data"))) return s.projectPath;
    } catch {}
  }
  const devPath = path.resolve(__dirname, "..");
  if (fs.existsSync(path.join(devPath, "data"))) return devPath;
  return null;
}

function saveProjectPath(p) {
  fs.writeFileSync(getSettingsPath(), JSON.stringify({ projectPath: p }), "utf-8");
}

let projectPath = null;

function getDataPath(file) {
  return path.join(projectPath, "data", file);
}

function readJSON(file) {
  const p = getDataPath(file);
  if (!fs.existsSync(p)) return null;
  return JSON.parse(fs.readFileSync(p, "utf-8"));
}

function writeJSON(file, data) {
  const p = getDataPath(file);
  fs.mkdirSync(path.dirname(p), { recursive: true });
  fs.writeFileSync(p, JSON.stringify(data, null, 2) + "\n", "utf-8");
}

// --- License System ---

const LICENSE_FILE = "license.json";
const REVALIDATE_DAYS = 7;
const LICENSE_API = "https://artstudio-license.etmatrix.workers.dev/api/licenses";

function getLicensePath() {
  return path.join(app.getPath("userData"), LICENSE_FILE);
}

function loadLicense() {
  const p = getLicensePath();
  if (!fs.existsSync(p)) return null;
  try {
    return JSON.parse(fs.readFileSync(p, "utf-8"));
  } catch {
    return null;
  }
}

function saveLicense(data) {
  fs.writeFileSync(getLicensePath(), JSON.stringify(data, null, 2), "utf-8");
}

function clearLicense() {
  const p = getLicensePath();
  if (fs.existsSync(p)) fs.unlinkSync(p);
}

function licenseRequest(endpoint, body) {
  return new Promise((resolve, reject) => {
    const postData = JSON.stringify(body);
    const url = new URL(`${LICENSE_API}/${endpoint}`);
    const req = https.request(
      {
        hostname: url.hostname,
        path: url.pathname,
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "Content-Length": Buffer.byteLength(postData),
          Accept: "application/json",
        },
      },
      (res) => {
        let data = "";
        res.on("data", (chunk) => (data += chunk));
        res.on("end", () => {
          try {
            resolve(JSON.parse(data));
          } catch {
            reject(new Error("Invalid response from license server"));
          }
        });
      }
    );
    req.on("error", reject);
    req.setTimeout(15000, () => {
      req.destroy();
      reject(new Error("License server timeout"));
    });
    req.write(postData);
    req.end();
  });
}

function getMachineId() {
  const os = require("os");
  return `${os.hostname()}-${os.userInfo().username}`;
}

async function activateLicense(licenseKey) {
  try {
    const result = await licenseRequest("activate", {
      license_key: licenseKey,
      instance_name: getMachineId(),
    });

    if (result.activated || result.valid) {
      const license = {
        key: licenseKey,
        status: "active",
        customerName: result.meta?.customer_name || "",
        customerEmail: result.meta?.customer_email || "",
        productName: result.meta?.product_name || "ArtStudio Pro",
        variant: result.meta?.variant_name || "Professional",
        activatedAt: new Date().toISOString(),
        validatedAt: new Date().toISOString(),
        expiresAt: result.license_key?.expires_at || null,
        instanceId: result.instance?.id || null,
        trial: !!result.trial,
        limits: result.limits || null,
      };
      saveLicense(license);
      return { success: true, license };
    }

    return {
      success: false,
      error: result.error || result.message || "Activation failed. Check your license key.",
    };
  } catch (err) {
    return { success: false, error: err.message };
  }
}

async function validateLicense() {
  const license = loadLicense();
  if (!license || !license.key) {
    return { valid: false, status: "no_license" };
  }

  const lastValidated = new Date(license.validatedAt);
  const daysSince = (Date.now() - lastValidated.getTime()) / (1000 * 60 * 60 * 24);

  if (daysSince < REVALIDATE_DAYS) {
    const expired = license.expiresAt && new Date(license.expiresAt) < new Date();
    return {
      valid: !expired,
      status: expired ? "expired" : "active",
      license,
      cached: true,
    };
  }

  try {
    const result = await licenseRequest("validate", {
      license_key: license.key,
      instance_id: license.instanceId,
    });

    if (result.valid) {
      license.validatedAt = new Date().toISOString();
      license.status = "active";
      license.expiresAt = result.license_key?.expires_at || license.expiresAt;
      license.trial = !!result.trial;
      license.limits = result.limits || null;
      saveLicense(license);
      return { valid: true, status: "active", license };
    }

    license.status = result.license_key?.status === "expired" ? "expired" : "invalid";
    saveLicense(license);
    return {
      valid: false,
      status: license.status,
      license,
      error: result.error || "License is no longer valid",
    };
  } catch {
    return {
      valid: true,
      status: "active",
      license,
      cached: true,
      offline: true,
    };
  }
}

async function deactivateLicense() {
  const license = loadLicense();
  if (!license || !license.key) return { success: true };

  try {
    await licenseRequest("deactivate", {
      license_key: license.key,
      instance_id: license.instanceId,
    });
  } catch {}

  clearLicense();
  return { success: true };
}

// --- Window ---

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1280,
    height: 860,
    minWidth: 900,
    minHeight: 600,
    title: "ArtStudio Pro — Admin Dashboard",
    backgroundColor: "#0f0f13",
    webPreferences: {
      preload: path.join(__dirname, "preload.js"),
      contextIsolation: true,
      nodeIntegration: false,
    },
  });

  mainWindow.loadFile(path.join(__dirname, "index.html"));
  mainWindow.setMenuBarVisibility(false);
}

app.whenReady().then(async () => {
  projectPath = loadProjectPath();
  createWindow();
  if (!projectPath) {
    const result = await dialog.showOpenDialog(mainWindow, {
      properties: ["openDirectory"],
      title: "Select Art Website Project Folder (the folder containing 'data/' and 'public/')",
    });
    if (result.filePaths[0]) {
      projectPath = result.filePaths[0];
      saveProjectPath(projectPath);
    } else {
      app.quit();
    }
  }
});
app.on("window-all-closed", () => app.quit());

// --- IPC: Project ---

ipcMain.handle("get-project-path", () => projectPath);

ipcMain.handle("set-project-path", async () => {
  const result = await dialog.showOpenDialog(mainWindow, {
    properties: ["openDirectory"],
    title: "Select Art Website Project Folder",
  });
  if (!result.canceled && result.filePaths[0]) {
    projectPath = result.filePaths[0];
    saveProjectPath(projectPath);
    return projectPath;
  }
  return null;
});

// --- IPC: Data ---

ipcMain.handle("load-paintings", () => readJSON("paintings.json") || []);
ipcMain.handle("save-paintings", (_, data) => {
  writeJSON("paintings.json", data);
  return true;
});

ipcMain.handle("load-events", () => readJSON("events.json") || []);
ipcMain.handle("save-events", (_, data) => {
  writeJSON("events.json", data);
  return true;
});

ipcMain.handle("load-config", () => readJSON("config.json") || {});
ipcMain.handle("save-config", (_, data) => {
  writeJSON("config.json", data);
  return true;
});

// --- IPC: Images ---

ipcMain.handle("upload-image", async (_, targetDir) => {
  const result = await dialog.showOpenDialog(mainWindow, {
    title: "Select Image",
    filters: [{ name: "Images", extensions: ["jpg", "jpeg", "png", "webp", "gif"] }],
    properties: ["openFile"],
  });
  if (result.canceled || !result.filePaths[0]) return null;

  const src = result.filePaths[0];
  const filename = Date.now() + "-" + path.basename(src);
  const destDir = path.join(projectPath, "public", "images", targetDir);
  fs.mkdirSync(destDir, { recursive: true });
  const dest = path.join(destDir, filename);
  fs.copyFileSync(src, dest);
  return `/images/${targetDir}/${filename}`;
});

// --- IPC: Commands ---

ipcMain.handle("run-command", (event, cmd, args) => {
  return new Promise((resolve) => {
    const child = spawn(cmd, args, {
      cwd: projectPath,
      shell: true,
      env: { ...process.env, FORCE_COLOR: "0" },
    });

    let output = "";

    child.stdout.on("data", (data) => {
      const text = data.toString();
      output += text;
      mainWindow.webContents.send("command-output", text);
    });

    child.stderr.on("data", (data) => {
      const text = data.toString();
      output += text;
      mainWindow.webContents.send("command-output", text);
    });

    child.on("close", (code) => {
      resolve({ code, output });
    });
  });
});

// --- IPC: License ---

ipcMain.handle("is-setup-complete", () => {
  if (!projectPath) return false;
  const cfg = readJSON("config.json");
  return !!(cfg && cfg.setupComplete);
});

ipcMain.handle("select-folder", async () => {
  const result = await dialog.showOpenDialog(mainWindow, {
    properties: ["openDirectory"],
    title: "Select a folder for your art website project",
  });
  if (!result.canceled && result.filePaths[0]) return result.filePaths[0];
  return null;
});

ipcMain.handle("scaffold-project", async (_, opts) => {
  const dest = opts.projectPath;
  if (!dest) return { success: false, error: "No project path" };

  const dataDir = path.join(dest, "data");
  const publicDir = path.join(dest, "public", "images");
  fs.mkdirSync(dataDir, { recursive: true });
  fs.mkdirSync(publicDir, { recursive: true });

  projectPath = dest;
  saveProjectPath(dest);

  writeJSON("paintings.json", []);
  writeJSON("events.json", []);
  writeJSON("config.json", {
    setupComplete: true,
    artistName: opts.artistName || "",
    brandName: opts.brandName || "",
    template: opts.template || "elegant",
    siteTitle: opts.siteTitle || opts.brandName || "Art Portfolio",
    socialLinks: {},
    contact: { email: opts.email || "" },
    testimonials: [],
    cloudflare: {
      projectName: opts.cfProject || "",
      apiToken: opts.cfToken || "",
    },
  });

  const templateName = opts.template || "elegant";
  const srcTemplate = app.isPackaged
    ? path.join(process.resourcesPath, "site-templates", templateName)
    : path.join(__dirname, "..", "site-templates", templateName);
  if (fs.existsSync(srcTemplate)) {
    copyDirSync(srcTemplate, dest);
  }

  return { success: true, projectPath: dest };
});

function copyDirSync(src, dest) {
  if (!fs.existsSync(src)) return;
  const entries = fs.readdirSync(src, { withFileTypes: true });
  for (const entry of entries) {
    const srcPath = path.join(src, entry.name);
    const destPath = path.join(dest, entry.name);
    if (entry.isDirectory()) {
      fs.mkdirSync(destPath, { recursive: true });
      copyDirSync(srcPath, destPath);
    } else if (!fs.existsSync(destPath)) {
      fs.copyFileSync(srcPath, destPath);
    }
  }
}

ipcMain.handle("deploy-site", async (_, opts) => {
  return new Promise((resolve) => {
    const args = ["wrangler", "pages", "deploy", "out/",
      "--project-name=" + (opts.projectName || "art-portfolio"),
      "--branch=main"];
    const env = { ...process.env, CLOUDFLARE_API_TOKEN: opts.cfToken };

    const child = spawn("npx", args, {
      cwd: projectPath,
      shell: true,
      env,
    });

    let output = "";
    child.stdout.on("data", (data) => {
      const text = data.toString();
      output += text;
      mainWindow.webContents.send("command-output", text);
    });
    child.stderr.on("data", (data) => {
      const text = data.toString();
      output += text;
      mainWindow.webContents.send("command-output", text);
    });
    child.on("close", (code) => {
      resolve({ code, output });
    });
  });
});

ipcMain.handle("activate-license", (_, key) => activateLicense(key));
ipcMain.handle("validate-license", () => validateLicense());
ipcMain.handle("get-license-status", () => {
  const license = loadLicense();
  if (!license) return { status: "no_license" };
  const expired = license.expiresAt && new Date(license.expiresAt) < new Date();
  return {
    status: expired ? "expired" : license.status,
    license,
  };
});
ipcMain.handle("deactivate-license", () => deactivateLicense());
