import prisma from '../lib/prisma';
import { notifyUser } from './notification.service';

/** Grace period before a deletion request is finalized (default 48 hours). */
export const ACCOUNT_DELETION_GRACE_HOURS = Math.max(
  1,
  parseInt(process.env.ACCOUNT_DELETION_GRACE_HOURS || '48', 10) || 48
);

export function computeDeletionSchedule(from = new Date()) {
  const scheduledFor = new Date(from.getTime() + ACCOUNT_DELETION_GRACE_HOURS * 60 * 60 * 1000);
  return { requestedAt: from, scheduledFor };
}

export async function requestAccountDeletion(userId: string, reason?: string) {
  const user = await prisma.user.findFirst({
    where: { id: userId, deletedAt: null, status: { not: 'DELETED' } },
  });
  if (!user) throw new Error('USER_NOT_FOUND');
  if (user.role === 'ADMIN') throw new Error('ADMIN_FORBIDDEN');
  if (user.deletionScheduledFor) throw new Error('ALREADY_REQUESTED');

  const { requestedAt, scheduledFor } = computeDeletionSchedule();
  const updated = await prisma.user.update({
    where: { id: userId },
    data: {
      deletionRequestedAt: requestedAt,
      deletionScheduledFor: scheduledFor,
      deletionReason: reason?.trim() ? reason.trim().slice(0, 1000) : null,
    },
    select: {
      id: true,
      email: true,
      role: true,
      deletionRequestedAt: true,
      deletionScheduledFor: true,
      deletionReason: true,
    },
  });

  await notifyUser({
    userId,
    type: 'SYSTEM',
    title: 'Account removal scheduled',
    message: `Your account is scheduled for removal on ${scheduledFor.toLocaleString('en-PH', {
      dateStyle: 'medium',
      timeStyle: 'short',
    })}. You can cancel anytime before then from your profile.`,
    data: {
      href: user.role === 'WORKER' ? '/worker/profile' : '/customer/profile',
      deletionScheduledFor: scheduledFor.toISOString(),
    },
    emailSubject: 'eHandyHire: Account removal scheduled',
    ctaLabel: 'Manage account',
    ctaPath: user.role === 'WORKER' ? '/worker/profile' : '/customer/profile',
  });

  return updated;
}

export async function cancelAccountDeletion(userId: string, byAdmin = false) {
  const user = await prisma.user.findFirst({
    where: {
      id: userId,
      deletedAt: null,
      deletionScheduledFor: { not: null },
    },
  });
  if (!user) throw new Error('NO_PENDING_REQUEST');

  const updated = await prisma.user.update({
    where: { id: userId },
    data: {
      deletionRequestedAt: null,
      deletionScheduledFor: null,
      deletionReason: null,
    },
    select: {
      id: true,
      email: true,
      role: true,
      deletionRequestedAt: true,
      deletionScheduledFor: true,
    },
  });

  await notifyUser({
    userId,
    type: 'SYSTEM',
    title: byAdmin ? 'Account removal cancelled by admin' : 'Account removal cancelled',
    message: byAdmin
      ? 'An admin cancelled your account removal request. Your account remains active.'
      : 'Your account removal request was cancelled. Your account remains active.',
    data: {
      href: user.role === 'WORKER' ? '/worker/profile' : '/customer/profile',
    },
    emailSubject: 'eHandyHire: Account removal cancelled',
    ctaLabel: 'Open profile',
    ctaPath: user.role === 'WORKER' ? '/worker/profile' : '/customer/profile',
  });

  return updated;
}

/**
 * Finalize account removal: anonymize PII, soft-delete worker profile, keep
 * historical records (reviews/messages) pointing at an anonymized user.
 */
export async function processAccountDeletion(userId: string) {
  const user = await prisma.user.findFirst({
    where: { id: userId, deletedAt: null, status: { not: 'DELETED' } },
    include: { workerProfile: { select: { id: true } } },
  });
  if (!user) return null;

  const anonymizedEmail = `deleted_${user.id.replace(/-/g, '').slice(0, 16)}@deleted.local`;

  await prisma.$transaction(async (tx) => {
    if (user.workerProfile) {
      await tx.workerProfile.update({
        where: { id: user.workerProfile.id },
        data: {
          deletedAt: new Date(),
          isAvailable: false,
          isHired: false,
          displayName: 'Deleted worker',
          headline: null,
          bio: null,
        },
      });

      await tx.hireInvitation.updateMany({
        where: { workerId: user.workerProfile.id, status: 'PENDING' },
        data: { status: 'CANCELLED', respondedAt: new Date() },
      });
    }

    await tx.hireInvitation.updateMany({
      where: { customerId: userId, status: 'PENDING' },
      data: { status: 'CANCELLED', respondedAt: new Date() },
    });

    await tx.user.update({
      where: { id: userId },
      data: {
        email: anonymizedEmail,
        phone: null,
        passwordHash: null,
        googleId: null,
        refreshToken: null,
        firstName: 'Deleted',
        lastName: 'User',
        avatarUrl: null,
        emailVerified: false,
        phoneVerified: false,
        status: 'DELETED',
        deletedAt: new Date(),
        deletionRequestedAt: null,
        deletionScheduledFor: null,
        deletionReason: null,
      },
    });
  });

  return { id: userId };
}

export async function processDueAccountDeletions() {
  const due = await prisma.user.findMany({
    where: {
      deletedAt: null,
      status: { not: 'DELETED' },
      deletionScheduledFor: { lte: new Date() },
    },
    select: { id: true },
    take: 50,
  });

  let processed = 0;
  for (const row of due) {
    try {
      await processAccountDeletion(row.id);
      processed += 1;
    } catch (err) {
      console.error(`Failed to process account deletion ${row.id}:`, err);
    }
  }
  return { due: due.length, processed };
}
