import 'server-only';

import { createHash, createHmac } from 'node:crypto';
import type { ResetPreviewReport, ResetScope, ReseedPreviewReport, ReseedTarget } from './reset-report';

const TOKEN_TTL_MS = 10 * 60 * 1000;

function getSecret() {
  return process.env.AUTH_SECRET || process.env.NEXTAUTH_SECRET || 'setup-reset-local-development-secret';
}

function encode(value: unknown) {
  return Buffer.from(JSON.stringify(value)).toString('base64url');
}

function decode<T>(value: string): T {
  return JSON.parse(Buffer.from(value, 'base64url').toString('utf8')) as T;
}

function sign(payload: string) {
  return createHmac('sha256', getSecret()).update(payload).digest('base64url');
}

export function hashPreviewPayload(payload: unknown) {
  return `sha256:${createHash('sha256').update(JSON.stringify(payload)).digest('hex')}`;
}

export function createConfirmationToken(input: {
  kind: 'reset' | 'reseed';
  scope?: ResetScope;
  target?: ReseedTarget;
  previewHash: string;
}) {
  const expiresAt = new Date(Date.now() + TOKEN_TTL_MS).toISOString();
  const payload = encode({ ...input, expiresAt });
  return {
    token: `${payload}.${sign(payload)}`,
    expiresAt
  };
}

export function validateConfirmationToken(input: {
  token: string;
  kind: 'reset' | 'reseed';
  scope?: ResetScope;
  target?: ReseedTarget;
  previewHash: string;
}) {
  const [payload, signature] = input.token.split('.');
  if (!payload || !signature || signature !== sign(payload)) {
    return 'Invalid confirmation token.';
  }

  const decoded = decode<{
    kind: 'reset' | 'reseed';
    scope?: ResetScope;
    target?: ReseedTarget;
    previewHash: string;
    expiresAt: string;
  }>(payload);

  if (decoded.kind !== input.kind) return 'Confirmation token kind mismatch.';
  if (decoded.scope !== input.scope) return 'Confirmation token scope mismatch.';
  if (decoded.target !== input.target) return 'Confirmation token target mismatch.';
  if (decoded.previewHash !== input.previewHash) return 'Confirmation token preview mismatch.';
  if (Date.parse(decoded.expiresAt) < Date.now()) return 'Confirmation token expired.';

  return null;
}

export function getEnvironmentBlockers() {
  const blockers: string[] = [];
  const nodeEnv = (process.env.NODE_ENV ?? '').toLowerCase();
  const databaseUrl = process.env.DATABASE_URL ?? '';

  if (nodeEnv === 'production') {
    blockers.push('Reset and reseed APIs are blocked when NODE_ENV=production.');
  }

  if (databaseUrl) {
    try {
      const parsed = new URL(databaseUrl);
      const host = parsed.hostname.toLowerCase();
      const databaseName = parsed.pathname.replace(/^\//, '').toLowerCase();
      const blockedFragments = ['prod', 'production', 'rds.amazonaws.com'];
      if (blockedFragments.some((fragment) => host.includes(fragment) || databaseName.includes(fragment))) {
        blockers.push('Reset and reseed APIs are blocked for production-like database hosts or names.');
      }
    } catch {
      blockers.push('DATABASE_URL could not be parsed for reset safety checks.');
    }
  }

  return blockers;
}

export function withToken<T extends ResetPreviewReport | ReseedPreviewReport>(
  report: Omit<T, 'confirmationToken' | 'expiresAt'>
): T {
  const token = createConfirmationToken({
    kind: 'scope' in report ? 'reset' : 'reseed',
    scope: 'scope' in report ? (report.scope as ResetScope) : undefined,
    target: 'target' in report ? (report.target as ReseedTarget) : undefined,
    previewHash: report.previewHash
  });

  return {
    ...report,
    confirmationToken: token.token,
    expiresAt: token.expiresAt
  } as T;
}
