import crypto from "crypto";
import {
  cookies,
  type UnsafeUnwrappedCookies,
} from "next/headers";
import { getClientIp, getUserAgent, shouldUseSecureCookies } from "@/lib/auth";
import { mailButton, mailCode, mailShell, sendToolaroMail } from "@/lib/mail";
import { prisma } from "@/lib/prisma";
import { hashIp, randomCode, randomToken, sha256 } from "@/lib/security";

export const ADMIN_SESSION_COOKIE = "toolaro_admin_session";

export function getAdminEmail() {
  return (process.env.ADMIN_EMAIL ?? "arthurkotsch@kotsch.tech").trim().toLowerCase();
}

function timingSafeStringEqual(left: string, right: string) {
  if (!left || !right) return false;
  const a = Buffer.from(left);
  const b = Buffer.from(right);
  if (a.length !== b.length) return false;
  return crypto.timingSafeEqual(a, b);
}

export function verifyAdminCredentials(email: string, password: string) {
  const expectedEmail = getAdminEmail();
  const expectedPassword = process.env.ADMIN_PASSWORD ?? process.env.ADMIN_SECRET ?? "";
  return timingSafeStringEqual(email.trim().toLowerCase(), expectedEmail) && timingSafeStringEqual(password, expectedPassword);
}

export async function createAdminLoginCode() {
  const code = randomCode(6);
  await prisma.adminLoginToken.create({
    data: {
      tokenHash: sha256(code),
      email: getAdminEmail(),
      requestedIpHash: hashIp(getClientIp()),
      expiresAt: new Date(Date.now() + 1000 * 60 * 10),
    },
  });

  await sendToolaroMail({
    to: getAdminEmail(),
    subject: "Toolaro Admin – Einmalcode",
    html: mailShell(
      "Admin-Einmalcode",
      `<p style="margin:0 0 4px;">Dein Admin-Einmalcode für Toolaro lautet:</p>
       ${mailCode(code)}
       <p style="margin:16px 0 0;font-size:13px;color:#4a5568;">Der Code ist <strong>10 Minuten</strong> gültig und kann nur einmal verwendet werden.<br>Falls du den Login nicht angefordert hast, ignoriere diese E-Mail.</p>`,
      `Admin-Einmalcode: ${code}`
    ),
    text: `Toolaro Admin-Einmalcode: ${code}\nGültig 10 Minuten, einmalig verwendbar.`,
  });
}

export async function createAdminLoginLink(baseUrl: string) {
  const token = randomToken(40);
  await prisma.adminLoginToken.create({
    data: {
      tokenHash: sha256(token),
      email: getAdminEmail(),
      requestedIpHash: hashIp(getClientIp()),
      expiresAt: new Date(Date.now() + 1000 * 60 * 10),
    },
  });

  const url = `${baseUrl.replace(/\/$/, "")}/api/admin/auth/confirm?token=${encodeURIComponent(token)}`;
  await sendToolaroMail({
    to: getAdminEmail(),
    subject: "Toolaro Admin – Login bestätigen",
    html: mailShell(
      "Admin-Login bestätigen",
      `<p style="margin:0 0 14px;">Es wurde ein Admin-Login für Toolaro angefordert. Klicke auf den Button, um den Zugang zu bestätigen.</p>
       ${mailButton("Admin-Login bestätigen", url)}
       <p style="margin:20px 0 0;font-size:13px;color:#4a5568;">Der Link ist <strong>10 Minuten</strong> gültig und einmalig verwendbar.<br>Falls du den Login nicht angefordert hast, ignoriere diese E-Mail.</p>`,
      "Admin-Login für Toolaro bestätigen."
    ),
    text: `Admin-Login bestätigen:\n${url}\n\nDer Link ist 10 Minuten gültig und einmalig verwendbar.`,
  });
}

export async function createAdminSession(email = getAdminEmail()) {
  const token = randomToken(48);
  const expiresAt = new Date(Date.now() + 1000 * 60 * 60 * 8);
  await prisma.adminSession.create({
    data: {
      sessionToken: sha256(token),
      email,
      ipHash: hashIp(getClientIp()),
      userAgent: getUserAgent().slice(0, 500),
      expiresAt,
    },
  });

  (cookies() as unknown as UnsafeUnwrappedCookies).set(ADMIN_SESSION_COOKIE, token, {
    httpOnly: true,
    sameSite: "lax",
    secure: shouldUseSecureCookies(),
    path: "/",
    expires: expiresAt,
  });
}

export async function getAdminSession() {
  const token = (cookies() as unknown as UnsafeUnwrappedCookies).get(ADMIN_SESSION_COOKIE)?.value;
  if (!token) return null;
  const session = await prisma.adminSession.findUnique({
    where: { sessionToken: sha256(token) },
  });
  if (!session || session.expiresAt <= new Date()) return null;
  await prisma.adminSession.update({
    where: { id: session.id },
    data: { lastSeenAt: new Date() },
  });
  return session;
}

export async function clearAdminSession() {
  const token = (cookies() as unknown as UnsafeUnwrappedCookies).get(ADMIN_SESSION_COOKIE)?.value;
  if (token) await prisma.adminSession.deleteMany({ where: { sessionToken: sha256(token) } });
  (cookies() as unknown as UnsafeUnwrappedCookies).delete(ADMIN_SESSION_COOKIE);
}
