import type { POStatus, Role } from "@prisma/client";

export type POAction =
  | "submit"
  | "approve"
  | "approve_with_note"
  | "reject"
  | "request_edits"
  | "request_vendor_id"
  | "provide_vendor_id"
  | "process_payment"
  | "mark_paid"
  | "mark_partial_payment"
  | "confirm_receipt"
  | "confirm_partial_receipt";

export type SideEffect =
  | "EMAIL_MANAGER"
  | "EMAIL_SUBMITTER"
  | "EMAIL_ACCOUNTS"
  | "EMAIL_SUBMITTER_AND_MANAGER";

interface Transition {
  to: POStatus;
  allowedRoles: Role[];
  requiresNote: boolean;
  sideEffects: SideEffect[];
}

type TransitionMap = Partial<Record<POAction, Transition>>;

const TRANSITIONS: Partial<Record<POStatus, TransitionMap>> = {
  DRAFT: {
    submit: {
      to: "SUBMITTED",
      allowedRoles: ["TECHNICAL", "MANNING", "MANAGER", "SUPERUSER"],
      requiresNote: false,
      sideEffects: ["EMAIL_MANAGER"],
    },
  },
  SUBMITTED: {
    // Auto-advances to MGR_REVIEW in the server action immediately after SUBMITTED
  },
  MGR_REVIEW: {
    approve: {
      to: "MGR_APPROVED",
      allowedRoles: ["MANAGER", "SUPERUSER"],
      requiresNote: false,
      sideEffects: ["EMAIL_SUBMITTER", "EMAIL_ACCOUNTS"],
    },
    approve_with_note: {
      to: "MGR_APPROVED",
      allowedRoles: ["MANAGER", "SUPERUSER"],
      requiresNote: true,
      sideEffects: ["EMAIL_SUBMITTER", "EMAIL_ACCOUNTS"],
    },
    reject: {
      to: "REJECTED",
      allowedRoles: ["MANAGER", "SUPERUSER"],
      requiresNote: true,
      sideEffects: ["EMAIL_SUBMITTER"],
    },
    request_edits: {
      to: "EDITS_REQUESTED",
      allowedRoles: ["MANAGER", "SUPERUSER"],
      requiresNote: true,
      sideEffects: ["EMAIL_SUBMITTER"],
    },
    request_vendor_id: {
      to: "VENDOR_ID_PENDING",
      allowedRoles: ["MANAGER", "SUPERUSER"],
      requiresNote: false,
      sideEffects: ["EMAIL_SUBMITTER"],
    },
  },
  VENDOR_ID_PENDING: {
    provide_vendor_id: {
      to: "MGR_REVIEW",
      allowedRoles: ["TECHNICAL", "MANNING", "ACCOUNTS", "MANAGER", "SUPERUSER"],
      requiresNote: false,
      sideEffects: ["EMAIL_MANAGER"],
    },
  },
  EDITS_REQUESTED: {
    submit: {
      to: "SUBMITTED",
      allowedRoles: ["TECHNICAL", "MANNING", "MANAGER", "SUPERUSER"],
      requiresNote: false,
      sideEffects: ["EMAIL_MANAGER"],
    },
  },
  MGR_APPROVED: {
    process_payment: {
      to: "SENT_FOR_PAYMENT",
      allowedRoles: ["ACCOUNTS", "SUPERUSER"],
      requiresNote: false,
      sideEffects: ["EMAIL_SUBMITTER_AND_MANAGER"],
    },
  },
  SENT_FOR_PAYMENT: {
    mark_paid: {
      to: "PAID_DELIVERED",
      allowedRoles: ["ACCOUNTS", "SUPERUSER", "MANAGER"],
      requiresNote: false,
      sideEffects: ["EMAIL_SUBMITTER", "EMAIL_MANAGER"],
    },
    mark_partial_payment: {
      to: "PARTIALLY_PAID",
      allowedRoles: ["ACCOUNTS", "SUPERUSER", "MANAGER"],
      requiresNote: false,
      sideEffects: [],
    },
  },
  PARTIALLY_PAID: {
    mark_paid: {
      to: "PAID_DELIVERED",
      allowedRoles: ["ACCOUNTS", "SUPERUSER", "MANAGER"],
      requiresNote: false,
      sideEffects: [],
    },
    mark_partial_payment: {
      to: "PARTIALLY_PAID",
      allowedRoles: ["ACCOUNTS", "SUPERUSER", "MANAGER"],
      requiresNote: false,
      sideEffects: [],
    },
    confirm_receipt: {
      to: "CLOSED",
      allowedRoles: ["TECHNICAL", "MANNING", "SUPERUSER", "MANAGER"],
      requiresNote: false,
      sideEffects: [],
    },
    confirm_partial_receipt: {
      to: "PARTIALLY_PAID",
      allowedRoles: ["TECHNICAL", "MANNING", "SUPERUSER", "MANAGER"],
      requiresNote: false,
      sideEffects: [],
    },
  },
  PAID_DELIVERED: {
    confirm_receipt: {
      to: "CLOSED",
      allowedRoles: ["TECHNICAL", "MANNING", "SUPERUSER", "MANAGER"],
      requiresNote: false,
      sideEffects: ["EMAIL_MANAGER", "EMAIL_ACCOUNTS"],
    },
    confirm_partial_receipt: {
      to: "PARTIALLY_CLOSED",
      allowedRoles: ["TECHNICAL", "MANNING", "SUPERUSER", "MANAGER"],
      requiresNote: false,
      sideEffects: [],
    },
  },
  PARTIALLY_CLOSED: {
    confirm_receipt: {
      to: "CLOSED",
      allowedRoles: ["TECHNICAL", "MANNING", "SUPERUSER", "MANAGER"],
      requiresNote: false,
      sideEffects: ["EMAIL_MANAGER", "EMAIL_ACCOUNTS"],
    },
    confirm_partial_receipt: {
      to: "PARTIALLY_CLOSED",
      allowedRoles: ["TECHNICAL", "MANNING", "SUPERUSER", "MANAGER"],
      requiresNote: false,
      sideEffects: [],
    },
  },
};

export function getTransition(from: POStatus, action: POAction): Transition | null {
  return TRANSITIONS[from]?.[action] ?? null;
}

export function canPerformAction(from: POStatus, action: POAction, role: Role): boolean {
  const transition = getTransition(from, action);
  return transition?.allowedRoles.includes(role) ?? false;
}

export function getAvailableActions(status: POStatus, role: Role): POAction[] {
  const map = TRANSITIONS[status];
  if (!map) return [];
  return (Object.keys(map) as POAction[]).filter((action) =>
    canPerformAction(status, action, role)
  );
}

export function requiresNote(from: POStatus, action: POAction): boolean {
  return getTransition(from, action)?.requiresNote ?? false;
}

// ── Cancellation ──────────────────────────────────────────────────────────────
// Cancellation is orthogonal to the normal lifecycle: a PO can be cancelled from
// ANY state (except when it is already cancelled), by a MANAGER or SUPERUSER, and
// always requires a reason. It is modelled separately from TRANSITIONS so it does
// not have to be enumerated on every source state.

export const CANCEL_ROLES: Role[] = ["MANAGER", "SUPERUSER"];

export function canCancel(from: POStatus, role: Role): boolean {
  return from !== "CANCELLED" && CANCEL_ROLES.includes(role);
}
