// lib/store.js — single-file local database (data/db.json) with atomic writes.
// Portable: copy data/db.json to move your whole library + settings anywhere.
import fs from "fs";
import path from "path";

const DATA_DIR = path.join(process.cwd(), "data");
const DB_PATH = path.join(DATA_DIR, "db.json");

export const DEFAULT_SETTINGS = {
  // Shown in the header of printed/exported assignments.
  profile: {
    teacherName: "",
    className: "",
    schoolName: "",
    logo: "", // small data-URL image (downscaled client-side before saving)
  },
  provider: "ollama",
  providers: {
    // Env overrides let the Docker image default to the host machine's
    // Ollama / LM Studio (host.docker.internal) without touching the UI.
    ollama: { baseUrl: process.env.OLLAMA_BASE_URL || "http://localhost:11434", model: "" },
    lmstudio: { baseUrl: process.env.LMSTUDIO_BASE_URL || "http://localhost:1234", model: "" },
    openai: { apiKey: "", model: "gpt-4o-mini" },
    anthropic: { apiKey: "", model: "claude-sonnet-4-6" },
    google: { apiKey: "", model: "gemini-2.0-flash" },
  },
  generation: {
    auto: true, // size maxTokens/maxSourceChars to the selected model (lib/model-caps.js)
    temperature: 0.3,
    maxTokens: 8000,
    maxSourceChars: 24000,
    verification: true,
  },
  // Optional: push quizzes straight into a Canvas course (lib/canvas/api.js).
  // baseUrl is the institution's Canvas, token is a personal access token.
  canvas: {
    baseUrl: "",
    token: "",
  },
};

function emptyDb() {
  return { assignments: [], settings: structuredClone(DEFAULT_SETTINGS) };
}

function readDb() {
  try {
    if (!fs.existsSync(DB_PATH)) return emptyDb();
    const raw = fs.readFileSync(DB_PATH, "utf8");
    const db = JSON.parse(raw);
    if (!Array.isArray(db.assignments)) db.assignments = [];
    db.settings = mergeSettings(db.settings);
    return db;
  } catch {
    // Corrupt file: keep a backup, start fresh rather than crash.
    try { fs.copyFileSync(DB_PATH, DB_PATH + ".corrupt-" + Date.now()); } catch {}
    return emptyDb();
  }
}

function writeDb(db) {
  fs.mkdirSync(DATA_DIR, { recursive: true });
  const tmp = DB_PATH + ".tmp";
  fs.writeFileSync(tmp, JSON.stringify(db, null, 2), "utf8");
  fs.renameSync(tmp, DB_PATH);
}

export function mergeSettings(saved) {
  const base = structuredClone(DEFAULT_SETTINGS);
  if (!saved || typeof saved !== "object") return base;
  const out = { ...base, ...saved };
  out.providers = { ...base.providers };
  for (const key of Object.keys(base.providers)) {
    out.providers[key] = { ...base.providers[key], ...(saved.providers?.[key] || {}) };
  }
  out.generation = { ...base.generation, ...(saved.generation || {}) };
  out.profile = { ...base.profile, ...(saved.profile || {}) };
  out.canvas = { ...base.canvas, ...(saved.canvas || {}) };
  return out;
}

// ---------- Settings ----------
export function getSettings() {
  return readDb().settings;
}

export function saveSettings(settings) {
  const db = readDb();
  db.settings = mergeSettings(settings);
  writeDb(db);
  return db.settings;
}

// ---------- Assignments ----------
export function listAssignments() {
  const db = readDb();
  return db.assignments
    .map((a) => ({
      id: a.id,
      title: a.title || "Untitled assignment",
      assignmentType: a.assignmentType,
      gradeLevel: a.gradeLevel,
      subject: a.subject,
      questionCount: (a.questions || []).length,
      totalPoints: (a.questions || []).reduce((s, q) => s + (Number(q.points) || 0), 0),
      createdAt: a.createdAt,
      updatedAt: a.updatedAt,
    }))
    .sort((x, y) => String(y.updatedAt).localeCompare(String(x.updatedAt)));
}

export function getAssignment(id) {
  return readDb().assignments.find((a) => a.id === id) || null;
}

export function createAssignment(assignment) {
  const db = readDb();
  const now = new Date().toISOString();
  const record = {
    ...assignment,
    id: assignment.id || "a_" + Date.now().toString(36) + Math.random().toString(36).slice(2, 7),
    createdAt: now,
    updatedAt: now,
  };
  db.assignments.push(record);
  writeDb(db);
  return record;
}

export function updateAssignment(id, patch) {
  const db = readDb();
  const idx = db.assignments.findIndex((a) => a.id === id);
  if (idx === -1) return null;
  db.assignments[idx] = {
    ...db.assignments[idx],
    ...patch,
    id,
    createdAt: db.assignments[idx].createdAt,
    updatedAt: new Date().toISOString(),
  };
  writeDb(db);
  return db.assignments[idx];
}

export function deleteAssignment(id) {
  const db = readDb();
  const before = db.assignments.length;
  db.assignments = db.assignments.filter((a) => a.id !== id);
  writeDb(db);
  return db.assignments.length < before;
}
