import { NextRequest, NextResponse } from "next/server";
import {
  db,
  AdminUser,
  hashPassword,
  generateTemporaryPassword,
  AdminRole,
  AdminStatus,
} from "@/lib/admin/db";
import { requireMainAdmin, getClientMetadata } from "@/lib/admin/auth";
import { SUB_ADMIN_ROLES } from "@/lib/admin/permissions";
import { sendMail } from "@/lib/mail";
import { renderEmail } from "@/emails/render";
import { AdminInvitationEmail } from "@/emails/templates/admin-invitation";

export const dynamic = "force-dynamic";

export async function GET(req: NextRequest) {
  try {
    await requireMainAdmin(req);

    const users = await db.getUsers();
    const sessions = await db.getSessions();
    const now = new Date().toISOString();
    const nowMs = Date.now();
    const inactivityLimitMs = 120 * 60 * 1000;

    const sanitizedUsers = users.map((u) => {
      const activeSessionsCount = sessions.filter((s) => {
        if (s.userId !== u.id) return false;
        if (s.revoked || s.status === "REVOKED" || s.status === "EXPIRED" || s.status === "BLOCKED") return false;
        if (s.expiresAt <= now) return false;
        const lastSeenMs = new Date(s.lastSeenAt || s.lastActiveAt || s.createdAt).getTime();
        if (nowMs - lastSeenMs > inactivityLimitMs) return false;
        return true;
      }).length;

      return {
        id: u.id,
        email: u.email,
        name: u.name,
        level: u.level,
        role: u.role,
        status: u.status,
        passwordChangeRequired: u.passwordChangeRequired,
        twoFactorEnabled: u.twoFactorEnabled,
        createdAt: u.createdAt,
        updatedAt: u.updatedAt,
        lastLoginAt: u.lastLoginAt,
        createdBy: u.createdBy,
        activeSessionsCount,
      };
    });

    return NextResponse.json({ users: sanitizedUsers });
  } catch (error) {
    const status = (error as unknown as { status: number }).status || 500;
    return NextResponse.json(
      { error: (error as Error).message || "Failed to load admin directory." },
      { status }
    );
  }
}

export async function POST(req: NextRequest) {
  try {
    const { user: mainAdmin } = await requireMainAdmin(req);
    const { ip } = getClientMetadata(req);

    const body = await req.json();
    const name = typeof body.name === "string" ? body.name.trim() : "";
    const email = typeof body.email === "string" ? body.email.trim().toLowerCase() : "";
    const role = body.role as AdminRole;
    const status = (body.status || "ACTIVE") as AdminStatus;

    if (!name || !email || !role) {
      return NextResponse.json(
        { error: "Name, email, and role are required fields." },
        { status: 400 }
      );
    }

    // Role must be a valid Sub-Admin role (cannot create another Main Admin via UI form)
    const validRole = SUB_ADMIN_ROLES.find((r) => r.id === role);
    if (!validRole) {
      return NextResponse.json(
        { error: `Invalid role selected. Permitted roles: ${SUB_ADMIN_ROLES.map((r) => r.id).join(", ")}` },
        { status: 400 }
      );
    }

    // Check duplicate email
    const existing = await db.getUserByEmail(email);
    if (existing) {
      return NextResponse.json(
        { error: `An administrator account with email ${email} already exists.` },
        { status: 409 }
      );
    }

    // Generate high-entropy temporary password
    const temporaryPassword = generateTemporaryPassword();
    const { hash, salt } = hashPassword(temporaryPassword);
    const now = new Date().toISOString();

    const newSubAdmin: AdminUser = {
      id: crypto.randomUUID(),
      email,
      name,
      level: "SUB_ADMIN",
      role,
      status: status === "SUSPENDED" ? "SUSPENDED" : "ACTIVE",
      passwordHash: hash,
      passwordSalt: salt,
      passwordChangeRequired: true,
      twoFactorEnabled: false,
      createdAt: now,
      updatedAt: now,
      lastLoginAt: null,
      createdBy: mainAdmin.id,
    };

    await db.createUser(newSubAdmin);

    // Record in Security Audit (NEVER log password!)
    await db.logSecurityEvent({
      actorId: mainAdmin.id,
      actorName: mainAdmin.name,
      actorEmail: mainAdmin.email,
      actorLevel: mainAdmin.level,
      targetUserId: newSubAdmin.id,
      targetUserEmail: newSubAdmin.email,
      targetUserName: newSubAdmin.name,
      action: "ADMIN_CREATED",
      details: {
        role: newSubAdmin.role,
        status: newSubAdmin.status,
        note: `Created by Main Admin ${mainAdmin.name}`,
      },
      ipAddress: ip,
    });

    // Send branded invitation email
    let emailSent = false;
    try {
      const { html, text } = await renderEmail(
        AdminInvitationEmail({
          name: newSubAdmin.name,
          email: newSubAdmin.email,
          roleLabel: validRole.label,
          temporaryPassword,
        })
      );

      await sendMail({
        to: newSubAdmin.email,
        subject: `Your Quto AI Admin Account — ${validRole.label}`,
        html,
        text,
      });
      emailSent = true;
    } catch (mailError) {
      console.error("[api/admin/users] Email invitation delivery error:", mailError);
    }

    return NextResponse.json({
      ok: true,
      user: {
        id: newSubAdmin.id,
        email: newSubAdmin.email,
        name: newSubAdmin.name,
        level: newSubAdmin.level,
        role: newSubAdmin.role,
        status: newSubAdmin.status,
      },
      temporaryPassword,
      emailSent,
      message: emailSent
        ? `Sub-admin account created. Invitation email sent to ${newSubAdmin.email}.`
        : `Sub-admin created, but the invitation email could not be delivered. Please share the temporary key manually.`,
    });
  } catch (error) {
    const status = (error as unknown as { status: number }).status || 500;
    return NextResponse.json(
      { error: (error as Error).message || "Failed to create sub-admin." },
      { status }
    );
  }
}
