"use server";

import { getServerSession } from "next-auth";
import { revalidatePath } from "next/cache";
import { authOptions } from "@/lib/auth";
import { isAdminEmail } from "@/lib/admin";
import {
  isReuploadField,
  organizerService,
  type ReuploadField,
} from "@/server/services/organizer.service";
import { auditLog } from "@/server/services/audit-log.service";
import { emailService } from "@/lib/email/send";
import { organizerRepo } from "@/server/repositories/organizer.repo";
import { userRepo } from "@/server/repositories/user.repo";
import { prisma } from "@/lib/prisma";
import { submitVerificationSchema, reviewVerificationSchema } from "./schemas";

export async function submitVerificationAction(formData: FormData) {
  const session = await getServerSession(authOptions);
  if (!session?.user) {
    return { error: "Kamu harus login terlebih dahulu" };
  }

  const raw = {
    fullName: formData.get("fullName") as string,
    nik: formData.get("nik") as string,
    birthDate: formData.get("birthDate") as string,
    address: formData.get("address") as string,
    ktpImageKey: formData.get("ktpImageKey") as string,
    livenessKey: formData.get("livenessKey") as string,
    bankName: formData.get("bankName") as string,
    bankAccountNumber: formData.get("bankAccountNumber") as string,
    bankAccountName: formData.get("bankAccountName") as string,
  };

  const result = submitVerificationSchema.safeParse(raw);
  if (!result.success) {
    return { error: result.error.issues[0].message };
  }

  try {
    await organizerService.submitVerification(session.user.id, {
      ...result.data,
      birthDate: new Date(result.data.birthDate),
    });
    void notifyKycSubmitted(session.user.id);
    revalidatePath("/verify");
    revalidatePath("/profile");
    revalidatePath("/admin/verifications");
    return { success: true };
  } catch (err) {
    return { error: (err as Error).message };
  }
}

export async function reviewVerificationAction(formData: FormData) {
  const session = await getServerSession(authOptions);
  if (!session?.user || !isAdminEmail(session.user.email)) {
    return { error: "Tidak memiliki akses admin" };
  }

  const raw = {
    verificationId: formData.get("verificationId") as string,
    decision: formData.get("decision") as string,
    rejectionReason: (formData.get("rejectionReason") as string) || undefined,
  };

  const result = reviewVerificationSchema.safeParse(raw);
  if (!result.success) {
    return { error: result.error.issues[0].message };
  }

  try {
    await organizerService.reviewVerification({
      verificationId: result.data.verificationId,
      decision: result.data.decision,
      rejectionReason: result.data.rejectionReason,
      reviewerId: session.user.id,
    });
    await auditLog.record({
      admin: { id: session.user.id, email: session.user.email },
      action:
        result.data.decision === "APPROVED"
          ? "VERIFICATION_APPROVE"
          : "VERIFICATION_REJECT",
      entityType: "OrganizerVerification",
      entityId: result.data.verificationId,
      payload:
        result.data.decision === "REJECTED"
          ? { rejectionReason: result.data.rejectionReason ?? null }
          : undefined,
    });

    // Notif email — fire and forget, jangan blok response.
    void notifyVerificationDecision(result.data.verificationId, result.data.decision, result.data.rejectionReason);

    revalidatePath("/admin/verifications");
    revalidatePath("/verify");
    revalidatePath("/profile");
    return { success: true };
  } catch (err) {
    return { error: (err as Error).message };
  }
}

async function notifyVerificationDecision(
  verificationId: string,
  decision: "APPROVED" | "REJECTED",
  rejectionReason?: string
) {
  const verification = await organizerRepo.findById(verificationId);
  if (!verification) return;
  const user = await userRepo.findById(verification.userId);
  if (!user) return;

  if (decision === "APPROVED") {
    await emailService.send({
      to: user.email,
      idempotencyKey: `kyc_approved-${verificationId}`,
      template: {
        template: "kyc_approved",
        data: { userName: user.name },
      },
    });
  } else {
    await emailService.send({
      to: user.email,
      // submissionCount supaya kalau reject berulang masing-masing dapat email.
      idempotencyKey: `kyc_rejected-${verificationId}-${verification.submissionCount}`,
      template: {
        template: "kyc_rejected",
        data: {
          userName: user.name,
          rejectionReason: rejectionReason ?? "(tidak ada alasan tercatat)",
        },
      },
    });
  }
}

/** E3.9 — kabari user kalau pengajuan verifikasi-nya sudah masuk antrian. */
async function notifyKycSubmitted(userId: string) {
  const verification = await prisma.organizerVerification.findUnique({
    where: { userId },
    select: { submissionCount: true },
  });
  const user = await userRepo.findById(userId);
  if (!verification || !user) return;
  await emailService.send({
    to: user.email,
    idempotencyKey: `kyc_submitted-${userId}-${verification.submissionCount}`,
    template: {
      template: "kyc_submitted",
      data: { userName: user.name },
    },
  });
}

/** E3.11 — kabari user kalau pengajuan verifikasi-nya dibuka kembali admin. */
async function notifyKycReopened(verificationId: string) {
  const verification = await organizerRepo.findById(verificationId);
  if (!verification) return;
  const user = await userRepo.findById(verification.userId);
  if (!user) return;
  await emailService.send({
    to: user.email,
    idempotencyKey: `kyc_reopened-${verificationId}-${verification.submissionCount}`,
    template: {
      template: "kyc_reopened",
      data: { userName: user.name },
    },
  });
}

/** E3.10 — kabari user kalau admin verifikasi dia secara manual override. */
async function notifyKycManualOverride(userId: string, verificationId: string) {
  const user = await userRepo.findById(userId);
  if (!user) return;
  await emailService.send({
    to: user.email,
    idempotencyKey: `kyc_manual_override-${verificationId}`,
    template: {
      template: "kyc_manual_override",
      data: { userName: user.name },
    },
  });
}

/**
 * Admin reopen pengajuan REJECTED ke PENDING — supaya organizer bisa
 * di-review ulang tanpa drop & recreate row. Note wajib min 10 char untuk audit.
 */
export async function reopenVerificationAction(
  verificationId: string,
  note: string
) {
  const session = await getServerSession(authOptions);
  if (!session?.user || !isAdminEmail(session.user.email)) {
    return { error: "Tidak memiliki akses admin" };
  }

  try {
    await organizerService.reopenVerification({
      verificationId,
      adminId: session.user.id,
      note,
    });
    void notifyKycReopened(verificationId);
    await auditLog.record({
      admin: { id: session.user.id, email: session.user.email },
      action: "VERIFICATION_REOPEN",
      entityType: "OrganizerVerification",
      entityId: verificationId,
      payload: { note: note.trim() },
    });
    revalidatePath("/admin/verifications");
    revalidatePath("/verify");
    revalidatePath("/profile");
    return { success: true as const };
  } catch (err) {
    return { error: (err as Error).message };
  }
}

/**
 * Phase 2: admin minta organizer upload ulang field tertentu — daripada
 * reject penuh, set flag `reuploadRequested` + daftar field + note.
 */
export async function requestReuploadAction(
  verificationId: string,
  fields: string[],
  note: string
) {
  const session = await getServerSession(authOptions);
  if (!session?.user || !isAdminEmail(session.user.email)) {
    return { error: "Tidak memiliki akses admin" };
  }
  const valid = fields.filter(isReuploadField) as ReuploadField[];

  try {
    await organizerService.requestReupload({
      verificationId,
      adminId: session.user.id,
      fields: valid,
      note,
    });
    await auditLog.record({
      admin: { id: session.user.id, email: session.user.email },
      action: "VERIFICATION_REQUEST_REUPLOAD",
      entityType: "OrganizerVerification",
      entityId: verificationId,
      payload: { fields: valid, note: note.trim() },
    });

    // Notif email organizer — urgent, action required.
    void notifyReuploadRequest(verificationId, valid, note.trim());

    revalidatePath("/admin/verifications");
    revalidatePath("/verify");
    return { success: true as const };
  } catch (err) {
    return { error: (err as Error).message };
  }
}

async function notifyReuploadRequest(
  verificationId: string,
  fields: ReuploadField[],
  note: string
) {
  const verification = await organizerRepo.findById(verificationId);
  if (!verification) return;
  const user = await userRepo.findById(verification.userId);
  if (!user) return;
  await emailService.send({
    to: user.email,
    // Allow re-trigger kalau admin minta lagi setelah submit ulang.
    idempotencyKey: `kyc_reupload_request-${verificationId}-${verification.submissionCount}`,
    template: {
      template: "kyc_reupload_request",
      data: {
        userName: user.name,
        fields,
        note,
      },
    },
  });
}

/**
 * Phase 4: admin verify user tanpa upload KYC (partner trusted referral).
 * Bikin row APPROVED dengan flag `isManualOverride = true`.
 */
export async function manualOverrideVerificationAction(input: {
  userId: string;
  note: string;
  bankName: string;
  bankAccountNumber: string;
  bankAccountName: string;
}) {
  const session = await getServerSession(authOptions);
  if (!session?.user || !isAdminEmail(session.user.email)) {
    return { error: "Tidak memiliki akses admin" };
  }

  try {
    const result = await organizerService.manualOverrideVerification({
      userId: input.userId,
      adminId: session.user.id,
      note: input.note,
      bankName: input.bankName,
      bankAccountNumber: input.bankAccountNumber,
      bankAccountName: input.bankAccountName,
    });
    void notifyKycManualOverride(input.userId, result.id);
    await auditLog.record({
      admin: { id: session.user.id, email: session.user.email },
      action: "VERIFICATION_MANUAL_OVERRIDE",
      entityType: "OrganizerVerification",
      entityId: result.id,
      payload: { userId: input.userId, note: input.note.trim() },
    });
    revalidatePath("/admin/verifications");
    revalidatePath(`/admin/users/${input.userId}`);
    revalidatePath("/verify");
    return { success: true as const, verificationId: result.id };
  } catch (err) {
    return { error: (err as Error).message };
  }
}
