/* eslint-disable no-console */
import { v } from "convex/values";
import { internalAction, internalMutation } from "./_generated/server";
import { internal } from "./_generated/api";
import type { Id } from "./_generated/dataModel";
import { createAccount } from "@convex-dev/auth/server";
import { PERMISSION_KEYS, ROLE_DEFAULTS, SYSTEM_ROLES } from "../src/lib/permissions";
import { DEFAULT_SETTINGS } from "../src/lib/settings-defaults";
import { NOTIFICATION_EVENTS } from "../src/lib/notification-events";

/**
 * First run on an empty production deployment: roles, settings, notification
 * rules and a single owner account. No demo data — unlike `seed:run`, which
 * wipes everything and fills the database with a fictional hotel.
 *
 *   npx convex run bootstrap:run '{"email":"you@yours.ma","password":"…","fullName":"Your Name","businessName":"…"}' --prod
 *
 * Refuses to touch a deployment that already has users, so it can never wipe
 * a live database by accident.
 */
export const prepare = internalMutation({
  args: { email: v.string(), fullName: v.string(), businessName: v.optional(v.string()), contactPhone: v.optional(v.string()) },
  returns: v.object({ status: v.string(), userId: v.union(v.id("users"), v.null()) }),
  handler: async (ctx, { email, fullName, businessName, contactPhone }) => {
    const existing = await ctx.db.query("users").take(1);
    if (existing.length) return { status: "already-initialised", userId: null };

    const roles: Record<string, Id<"roles">> = {};
    for (const r of SYSTEM_ROLES) roles[r.key] = await ctx.db.insert("roles", { key: r.key, name: r.name, description: r.description, isSystem: true, permissions: r.key === "ADMIN" ? PERMISSION_KEYS : ROLE_DEFAULTS[r.key] });

    const now = Date.now();
    const settings = { ...DEFAULT_SETTINGS, ...(businessName ? { businessName } : {}), ...(contactPhone ? { contactPhone } : {}) };
    for (const [key, value] of Object.entries(settings)) await ctx.db.insert("settings", { key, value, group: "general", updatedAt: now });
    for (const e of NOTIFICATION_EVENTS) await ctx.db.insert("notificationRules", { eventType: e.type, label: e.label, enabled: true, inApp: true, email: e.defaultPriority === "CRITICAL", push: false, priority: e.defaultPriority, recipientRoles: e.defaultRole ? [e.defaultRole] : [], recipientUserIds: [], notifyActor: false, notifyAssigned: e.notifyAssigned });

    const userId = await ctx.db.insert("users", { code: "WRK-0001", email, name: fullName, fullName, username: email.split("@")[0], roleId: roles.ADMIN, status: "ACTIVE", locale: "en", timezone: settings.timezone, twoFactorEnabled: false, permissionOverrides: [], hireDate: new Date(now).toISOString().slice(0, 10) });
    await ctx.db.insert("sequences", { name: "worker", value: 1 });
    return { status: "created", userId };
  },
});

export const run = internalAction({
  args: { email: v.string(), password: v.string(), fullName: v.optional(v.string()), businessName: v.optional(v.string()), contactPhone: v.optional(v.string()) },
  returns: v.string(),
  handler: async (ctx, { email, password, fullName, businessName, contactPhone }) => {
    if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) throw new Error("Give a valid email address.");
    if (password.length < 8) throw new Error("Use a password of at least 8 characters.");
    const r = await ctx.runMutation(internal.bootstrap.prepare, { email, fullName: fullName ?? "Owner", businessName, contactPhone });
    if (r.status === "already-initialised") return "This deployment already has users — nothing was changed.";
    await createAccount(ctx, { provider: "password", account: { id: email, secret: password }, profile: { email } });
    console.log(`Owner account ready: ${email}`);
    return `Ready. Sign in at your site with ${email}.`;
  },
});
