"use server";

import { auth } from "@/auth";
import { db } from "@/lib/db";
import { hasPermission, type Permission } from "@/lib/permissions";
import { CREWING_ENABLED } from "@/lib/feature-flags";
import type { Role } from "@prisma/client";
import { revalidatePath } from "next/cache";

type ActionResult = { ok: true } | { error: string };
const PATH = "/crewing/verification";

async function guard(permission: Permission): Promise<{ error: string } | { userId: string; role: Role }> {
  if (!CREWING_ENABLED) return { error: "Crewing is not enabled" };
  const session = await auth();
  if (!session?.user) return { error: "Unauthorized" };
  if (!hasPermission(session.user.role, permission)) return { error: "Unauthorized" };
  return { userId: session.user.id, role: session.user.role };
}

// ── Document verification (MPO / Manager) ──────────────────────────────────────

export async function verifyDocument(id: string, approve: boolean, remarks?: string): Promise<ActionResult> {
  const g = await guard("verify_site_records");
  if ("error" in g) return g;
  if (!approve && !remarks?.trim()) return { error: "A reason is required to reject" };

  const doc = await db.seafarerDocument.findUnique({ where: { id }, select: { crewMemberId: true, verificationStatus: true } });
  if (!doc) return { error: "Document not found" };
  if (doc.verificationStatus !== "PENDING") return { error: `This document is already ${doc.verificationStatus.toLowerCase()}` };

  await db.seafarerDocument.update({
    where: { id },
    data: { verificationStatus: approve ? "VERIFIED" : "REJECTED", verifiedById: g.userId },
  });
  await db.crewAction.create({
    data: {
      actionType: approve ? "RECORD_VERIFIED" : "RECORD_REJECTED",
      actorId: g.userId,
      crewMemberId: doc.crewMemberId,
      note: remarks?.trim() || null,
      metadata: { record: "document" },
    },
  });

  revalidatePath(PATH);
  revalidatePath(`/crewing/crew/${doc.crewMemberId}`);
  return { ok: true };
}

// ── Bank / EPF verification (Accounts) ─────────────────────────────────────────

export async function verifyBankEpf(crewMemberId: string, kind: "bank" | "epf", approve: boolean, remarks?: string): Promise<ActionResult> {
  const g = await guard("verify_bank_epf");
  if ("error" in g) return g;
  if (!approve && !remarks?.trim()) return { error: "A reason is required to reject" };

  const status = approve ? "VERIFIED" : "REJECTED";
  if (kind === "bank") {
    const rec = await db.bankDetail.findUnique({ where: { crewMemberId }, select: { id: true, verificationStatus: true } });
    if (!rec) return { error: "Bank details not found" };
    if (rec.verificationStatus !== "PENDING") return { error: `Bank details already ${rec.verificationStatus.toLowerCase()}` };
    await db.bankDetail.update({ where: { crewMemberId }, data: { verificationStatus: status, verifiedById: g.userId } });
  } else {
    const rec = await db.epfDetail.findUnique({ where: { crewMemberId }, select: { id: true, verificationStatus: true } });
    if (!rec) return { error: "EPF details not found" };
    if (rec.verificationStatus !== "PENDING") return { error: `EPF details already ${rec.verificationStatus.toLowerCase()}` };
    await db.epfDetail.update({ where: { crewMemberId }, data: { verificationStatus: status, verifiedById: g.userId } });
  }

  await db.crewAction.create({
    data: {
      actionType: approve ? "RECORD_VERIFIED" : "RECORD_REJECTED",
      actorId: g.userId,
      crewMemberId,
      note: remarks?.trim() || null,
      metadata: { record: kind },
    },
  });

  revalidatePath(PATH);
  revalidatePath(`/crewing/crew/${crewMemberId}`);
  return { ok: true };
}

// ── PPE / next-of-kin verification (MPO) ───────────────────────────────────────

async function verifyRecord(
  load: () => Promise<{ crewMemberId: string; verificationStatus: "PENDING" | "VERIFIED" | "REJECTED" } | null>,
  set: (status: "VERIFIED" | "REJECTED", userId: string) => Promise<unknown>,
  recordLabel: string,
  approve: boolean,
  remarks: string | undefined,
  userId: string
): Promise<ActionResult> {
  if (!approve && !remarks?.trim()) return { error: "A reason is required to reject" };
  const rec = await load();
  if (!rec) return { error: "Record not found" };
  if (rec.verificationStatus !== "PENDING") return { error: `This record is already ${rec.verificationStatus.toLowerCase()}` };

  await set(approve ? "VERIFIED" : "REJECTED", userId);
  await db.crewAction.create({
    data: { actionType: approve ? "RECORD_VERIFIED" : "RECORD_REJECTED", actorId: userId, crewMemberId: rec.crewMemberId, note: remarks?.trim() || null, metadata: { record: recordLabel } },
  });
  revalidatePath(PATH);
  revalidatePath(`/crewing/crew/${rec.crewMemberId}`);
  return { ok: true };
}

export async function verifyPpe(id: string, approve: boolean, remarks?: string): Promise<ActionResult> {
  const g = await guard("verify_site_records");
  if ("error" in g) return g;
  return verifyRecord(
    () => db.ppeIssue.findUnique({ where: { id }, select: { crewMemberId: true, verificationStatus: true } }),
    (status, userId) => db.ppeIssue.update({ where: { id }, data: { verificationStatus: status, verifiedById: userId } }),
    "ppe",
    approve,
    remarks,
    g.userId
  );
}

export async function verifyNextOfKin(id: string, approve: boolean, remarks?: string): Promise<ActionResult> {
  const g = await guard("verify_site_records");
  if ("error" in g) return g;
  return verifyRecord(
    () => db.nextOfKin.findUnique({ where: { id }, select: { crewMemberId: true, verificationStatus: true } }),
    (status, userId) => db.nextOfKin.update({ where: { id }, data: { verificationStatus: status, verifiedById: userId } }),
    "next_of_kin",
    approve,
    remarks,
    g.userId
  );
}

// ── EPFO assisted lookup (Accounts) ────────────────────────────────────────────
// Records the result of an EpfoService UAN check on the crew member's EpfDetail
// (A3 "record the result"). The actual lookup runs in the browser via /api/epfo;
// this just persists the returned member name + a timestamp for the audit trail.

export async function recordEpfoCheck(crewMemberId: string, memberName: string | null): Promise<ActionResult> {
  const g = await guard("verify_bank_epf");
  if ("error" in g) return g;

  const rec = await db.epfDetail.findUnique({ where: { crewMemberId }, select: { id: true } });
  if (!rec) return { error: "EPF details not found" };

  await db.epfDetail.update({
    where: { crewMemberId },
    data: { epfoMemberName: memberName, epfoCheckedAt: new Date() },
  });
  await db.crewAction.create({
    data: {
      actionType: "RECORD_UPDATED",
      actorId: g.userId,
      crewMemberId,
      note: memberName ? `EPFO check matched: ${memberName}` : "EPFO check: no match",
      metadata: { record: "epfo_check" },
    },
  });

  revalidatePath(PATH);
  revalidatePath(`/crewing/crew/${crewMemberId}`);
  return { ok: true };
}
