import { existsSync, readFileSync } from "node:fs";
import { join } from "node:path";
import { randomUUID } from "node:crypto";
import { ensureSecureDir, writeSecureFile } from "./fs-permissions.js";
import { createLogger } from "./logger.js";

const log = createLogger("template-manager");

export interface SessionTemplateConfig {
  backend: "claude" | "codex";
  model?: string;
  permissionMode?: string;
  cwd?: string;
  envSlug?: string;
  codexInternetAccess?: boolean;
}

export interface SessionTemplate {
  id: string;
  name: string;
  description: string;
  config: SessionTemplateConfig;
  createdAt: number;
  updatedAt: number;
}

export interface TemplateUpdateFields {
  name?: string;
  description?: string;
  config?: SessionTemplateConfig;
}

import { ZENCODE_DIR } from "./config.js";

const TEMPLATES_FILE = join(ZENCODE_DIR, "session-templates.json");

function ensureDir(): void {
  ensureSecureDir(ZENCODE_DIR);
}

function loadTemplates(): SessionTemplate[] {
  ensureDir();
  if (!existsSync(TEMPLATES_FILE)) return [];
  try {
    const raw = readFileSync(TEMPLATES_FILE, "utf-8");
    const parsed = JSON.parse(raw) as unknown;
    if (!Array.isArray(parsed)) return [];
    return parsed.filter((t): t is SessionTemplate => {
      if (!t || typeof t !== "object") return false;
      const candidate = t as Partial<SessionTemplate>;
      return (
        typeof candidate.id === "string"
        && typeof candidate.name === "string"
        && typeof candidate.config === "object"
        && candidate.config !== null
      );
    });
  } catch (err) {
    log.warn({ err }, "Failed to load session templates");
    return [];
  }
}

function saveTemplates(templates: SessionTemplate[]): void {
  ensureDir();
  writeSecureFile(TEMPLATES_FILE, JSON.stringify(templates, null, 2));
}

function sortTemplates(templates: SessionTemplate[]): SessionTemplate[] {
  return [...templates].sort((a, b) => b.updatedAt - a.updatedAt || a.name.localeCompare(b.name));
}

export function listTemplates(): SessionTemplate[] {
  return sortTemplates(loadTemplates());
}

export function getTemplate(id: string): SessionTemplate | null {
  return loadTemplates().find((t) => t.id === id) ?? null;
}

export function createTemplate(
  name: string,
  description: string,
  config: SessionTemplateConfig,
): SessionTemplate {
  const cleanName = name?.trim();
  if (!cleanName) throw new Error("Template name is required");

  const templates = loadTemplates();
  const now = Date.now();
  const template: SessionTemplate = {
    id: randomUUID(),
    name: cleanName,
    description: (description ?? "").trim(),
    config,
    createdAt: now,
    updatedAt: now,
  };
  templates.push(template);
  saveTemplates(templates);
  return template;
}

export function updateTemplate(id: string, updates: TemplateUpdateFields): SessionTemplate | null {
  const templates = loadTemplates();
  const index = templates.findIndex((t) => t.id === id);
  if (index < 0) return null;

  if (updates.name !== undefined && !updates.name.trim()) {
    throw new Error("Template name cannot be empty");
  }

  const updated: SessionTemplate = {
    ...templates[index],
    name: updates.name !== undefined ? updates.name.trim() : templates[index].name,
    description: updates.description !== undefined ? updates.description.trim() : templates[index].description,
    config: updates.config !== undefined ? updates.config : templates[index].config,
    updatedAt: Date.now(),
  };
  templates[index] = updated;
  saveTemplates(templates);
  return updated;
}

export function deleteTemplate(id: string): boolean {
  const templates = loadTemplates();
  const next = templates.filter((t) => t.id !== id);
  if (next.length === templates.length) return false;
  saveTemplates(next);
  return true;
}
