import { organizerRepo } from "@/server/repositories/organizer.repo";
import { decryptString, encryptString, hmacHex } from "@/lib/crypto";

type SubmitInput = {
  fullName: string;
  nik: string;
  birthDate: Date;
  address: string;
  ktpImageKey: string;
  livenessKey: string;
  bankName: string;
  bankAccountNumber: string;
  bankAccountName: string;
};

export const organizerService = {
  async submitVerification(userId: string, data: SubmitInput) {
    const existing = await organizerRepo.findByUserId(userId);
    if (existing && existing.status === "APPROVED") {
      throw new Error("Akun kamu sudah terverifikasi");
    }
    if (existing && existing.status === "PENDING") {
      throw new Error("Pengajuan kamu masih dalam proses review");
    }

    const nikHash = hmacHex(data.nik);
    const dupNik = await organizerRepo.findByNikHash(nikHash);
    if (dupNik && dupNik.userId !== userId) {
      throw new Error("NIK ini sudah dipakai akun lain");
    }

    return organizerRepo.upsertForUser(userId, {
      fullName: data.fullName,
      nikEncrypted: encryptString(data.nik),
      nikHash,
      birthDate: data.birthDate,
      address: data.address,
      ktpImageKey: data.ktpImageKey,
      livenessKey: data.livenessKey,
      bankName: data.bankName,
      bankAccountNumber: data.bankAccountNumber,
      bankAccountName: data.bankAccountName,
      status: "PENDING",
      rejectionReason: null,
      reviewedAt: null,
      reviewedById: null,
      verifiedAt: null,
    });
  },

  async reviewVerification(input: {
    verificationId: string;
    decision: "APPROVED" | "REJECTED";
    rejectionReason?: string;
    reviewerId: string;
  }) {
    const verification = await organizerRepo.findById(input.verificationId);
    if (!verification) {
      throw new Error("Pengajuan tidak ditemukan");
    }
    if (verification.status !== "PENDING") {
      throw new Error("Pengajuan ini sudah diproses");
    }

    return organizerRepo.updateReview(input.verificationId, {
      status: input.decision,
      rejectionReason: input.decision === "REJECTED" ? input.rejectionReason ?? null : null,
      reviewedById: input.reviewerId,
    });
  },

  async getStatusForUser(userId: string) {
    return organizerRepo.findByUserId(userId);
  },

  async isApproved(userId: string) {
    const v = await organizerRepo.findByUserId(userId);
    return v?.status === "APPROVED";
  },

  /** Reveal NIK plaintext. Caller must enforce authorization (owner or admin). */
  decryptNik(nikEncrypted: string): string {
    return decryptString(nikEncrypted);
  },
};
