/* Creates (or promotes) a staff account. Never ships default credentials.
   Interactive:   npm run admin:create
   Non-interactive (CI/servers):  ADMIN_EMAIL=... ADMIN_NAME=... ADMIN_PASSWORD=... ADMIN_ROLE=OWNER npm run admin:create */
import "dotenv/config";
import { createInterface } from "readline/promises";
import { stdin, stdout } from "process";
import bcrypt from "bcryptjs";
import { PrismaClient, type Role } from "@prisma/client";
import { PrismaMariaDb } from "@prisma/adapter-mariadb";

const url = new URL(process.env.DATABASE_URL!);
const db = new PrismaClient({ adapter: new PrismaMariaDb({ host: url.hostname, port: Number(url.port || 3306), user: decodeURIComponent(url.username), password: url.password ? decodeURIComponent(url.password) : undefined, database: url.pathname.slice(1), connectionLimit: 1, allowPublicKeyRetrieval: true }) });

async function ask(rl: ReturnType<typeof createInterface>, q: string, hidden = false) {
  if (!hidden) return (await rl.question(q)).trim();
  // Hide password input
  const out = stdout as unknown as { write: (s: string) => boolean };
  const orig = out.write.bind(out);
  let muted = false;
  (stdout as unknown as { write: (s: string) => boolean }).write = (s: string) => (muted && !s.includes(q) ? true : orig(s));
  const p = rl.question(q);
  muted = true;
  const ans = await p;
  muted = false;
  (stdout as unknown as { write: (s: string) => boolean }).write = orig;
  orig("\n");
  return ans;
}

async function main() {
  let email = process.env.ADMIN_EMAIL, name = process.env.ADMIN_NAME, password = process.env.ADMIN_PASSWORD;
  const role = (process.env.ADMIN_ROLE || "OWNER") as Role;
  if (!["OWNER", "MANAGER", "EDITOR", "FULFILLMENT"].includes(role)) throw new Error("ADMIN_ROLE must be OWNER, MANAGER, EDITOR or FULFILLMENT");
  if (!email || !password) {
    const rl = createInterface({ input: stdin, output: stdout });
    email = email || (await ask(rl, "Admin email: "));
    name = name || (await ask(rl, "Full name: "));
    password = await ask(rl, "Password (min 12 chars, letters + numbers): ", true);
    const again = await ask(rl, "Repeat password: ", true);
    rl.close();
    if (password !== again) throw new Error("Passwords don't match.");
  }
  email = email.toLowerCase();
  if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) throw new Error("Enter a valid email.");
  if (password.length < 12 || !/[A-Za-z]/.test(password) || !/\d/.test(password)) throw new Error("Use at least 12 characters with letters and numbers.");
  const passwordHash = await bcrypt.hash(password, 12);
  const user = await db.user.upsert({
    where: { email },
    create: { email, name: name || email.split("@")[0], passwordHash, role },
    update: { passwordHash, role, active: true, sessionVer: { increment: 1 } },
  });
  await db.auditLog.create({ data: { actorId: user.id, action: "team.create_admin_cli", entity: "User", entityId: user.id, meta: { role } } });
  console.log(`✔ ${role} account ready for ${email}. Sign in at /admin/login`);
}

main().then(() => db.$disconnect()).catch(async (e) => { console.error("✖", e.message); await db.$disconnect(); process.exit(1); });
