/**
 * Customer-management types for the freight backoffice.
 *
 * These mirror the backend `Company` / `CompanyProfile` entities
 * (apps/edr-freight-api/src/modules/companies/entities) plus a few lightweight
 * shapes for the related data shown on the detail page (bookings / documents /
 * payments). The UI is currently driven by mock data, but the shapes match the
 * API so the data layer can be swapped to live endpoints with no UI changes.
 */

/** Mirrors backend `CompanyType`. */
export type CompanyType =
  | "customer"
  | "freight_forwarder"
  | "dj_freight_forwarder"
  | "transporter";

/** Mirrors backend `CompanyStatus`. */
export type CompanyStatus = "active" | "pending" | "suspended" | "blacklisted";

/** Mirrors backend `CompanyKind` — commercial customer vs. government entity. */
export type CompanyKind = "commercial" | "government";

/** Mirrors backend `ProfileType` (the role a company plays). */
export type ProfileType =
  | "importer"
  | "exporter"
  | "freight_forwarder"
  | "dj_freight_forwarder"
  | "transporter";

/** Mirrors backend `ProfileStatus`. */
export type ProfileStatus =
  | "active"
  | "pending"
  | "rejected"
  | "suspended"
  | "blacklisted";

/** Review state of a business-license file (mirrors API ProfileLicenseFileView). */
export type LicenseFileStatus = "live" | "pending_add" | "pending_remove";

/** A business-license document uploaded for a company profile (FileRecord-backed). */
export interface LicenseFile {
  id: string;
  name: string;
  size: number;
  mimeType: string;
  /** `live` = approved; `pending_add`/`pending_remove` = awaiting review. */
  status: LicenseFileStatus;
}

/** A single role a company is registered for, with its reference code. */
export interface CompanyProfile {
  id: string;
  companyId: string;
  type: ProfileType;
  reference: string;
  status: ProfileStatus;
  /** @deprecated Superseded by licenseFiles (file model). */
  businessLicense?: string | null;
  /** Business-license documents uploaded for this profile. */
  licenseFiles?: LicenseFile[];
  attributes?: Record<string, unknown> | null;
  /** Reviewer note when the role is rejected. */
  reviewNote?: string | null;
  createdAt: string;
  updatedAt: string;
}

/** Lifecycle of a staged customer profile-edit review. */
export type ChangeRequestStatus = "pending" | "approved" | "rejected";

/** A staged business-license add/remove on one profile, awaiting review. */
export interface LicenseChangeIntent {
  profileId: string;
  op: "add" | "remove";
  fileId: string;
  fileName?: string;
}

/** A staged company-level document add/remove (e.g. the PoA delegation letter). */
export interface DocumentChangeIntent {
  op: "add" | "remove";
  fileId: string;
  /** The live FileRecord code this op targets (the upload setting's fileKey). */
  code: string;
  fileName?: string;
}

/**
 * A staged profile-edit change request. The customer's settings edits land here
 * (pending) until a reviewer approves (applies them) or rejects (with a note).
 */
export interface CompanyChangeRequest {
  id: string;
  companyId: string;
  status: ChangeRequestStatus;
  /** Proposed field values (the diff payload vs. the live company). */
  snapshot: Record<string, unknown>;
  documentFileIds: string[];
  /** Staged business-license add/remove intents attached to this request. */
  licenseChanges: LicenseChangeIntent[];
  /** Staged company-document add/remove intents (e.g. the PoA letter). */
  documentChanges: DocumentChangeIntent[];
  note: string | null;
  submittedAt: string | null;
  reviewedAt: string | null;
  createdAt: string;
  updatedAt: string;
}

/** The channel a customer's password-reset link is delivered over. */
export type ResetChannel = "email" | "phone";

export interface ResetPasswordResult {
  channel: ResetChannel;
  /** Where the link went, e.g. `+251•••4821` — safe to show to staff. */
  maskedTarget: string;
  /** ISO timestamp after which the link stops working. */
  expiresAt: string;
}

/**
 * The IAM account a reset link would reach — the company's primary contact.
 * Distinct from `Company.email` / `Company.phone`, which are business contact
 * details and routinely differ from the credentials the customer logs in with.
 */
export interface CustomerResetTarget {
  userId: string;
  name: string;
  email: string | null;
  phone: string | null;
  /** SMS gateway is domestic-only; `false` means SMS can't reach this phone. `null` = no phone. */
  phoneIsDomestic: boolean | null;
}

/** Mirrors backend `Company` (+ its `companyProfiles`). */
export interface Company {
  id: string;
  name: string;
  type: CompanyType;
  kind: CompanyKind;
  status: CompanyStatus;
  tin: string;
  vatNumber?: string | null;
  fanNumber?: string | null;
  country: string;
  address?: string | null;
  phone?: string | null;
  email?: string | null;
  contactPersonName?: string | null;
  contactPersonPhone?: string | null;
  generalManagerName?: string | null;
  generalManagerEmail?: string | null;
  generalManagerPhone?: string | null;
  poaName?: string | null;
  poaEmail?: string | null;
  poaPhone?: string | null;
  poaLocation?: string | null;
  poaAddress?: string | null;
  website?: string | null;
  attributes?: Record<string, unknown> | null;
  companyProfiles: CompanyProfile[];
  /**
   * Whether the customer submitted their onboarding application. A company row
   * is created on the wizard's first click, so a `pending` company with this
   * false is a half-filled draft — not reviewable. Staff-created companies are
   * always true. Undefined on endpoints that don't load external profiles.
   */
  onboardingCompleted?: boolean;
  createdAt: string;
  updatedAt: string;
}

/**
 * Whether the customer has submitted their onboarding application. Mirrors the
 * API's review gate (`setCompanyProfileStatus`): until this is true, a role
 * awaiting a decision cannot be approved or rejected. Companies loaded without
 * external profiles (`undefined`) are treated as submitted — absence of the
 * flag must not lock staff out.
 */
export function hasSubmittedOnboarding(company: Company): boolean {
  return company.onboardingCompleted !== false;
}

/**
 * A pristine draft: still `pending` and never submitted, so its name/TIN are
 * placeholders and there is nothing to review. Drives presentation only — the
 * approval gate is `hasSubmittedOnboarding`, which also covers the (corrupted)
 * case of a company activated before that gate existed.
 */
export function isOnboardingDraft(company: Company): boolean {
  return company.status === "pending" && !hasSubmittedOnboarding(company);
}

/** Query parameters for the company list. */
export interface CompanyListFilter {
  page: number;
  pageSize: number;
  search?: string;
  type?: CompanyType;
  kind?: CompanyKind;
  status?: CompanyStatus;
  /** `true` = submitted applications only; `false` = drafts only; omit for both. */
  onboardingCompleted?: boolean;
  /**
   * `true` = only customers with an open profile change request. They are
   * already `active`, so `status` alone can never surface them.
   */
  hasPendingChangeRequest?: boolean;
  /** `review` = queue ordering: awaiting first approval → pending changes → rest, newest first within each. */
  sortBy?: "review" | "name" | "createdAt" | "updatedAt";
  sortOrder?: "ASC" | "DESC";
}

/** Standard paginated list envelope (matches the bookings service shape). */
export interface PaginatedCompanies {
  items: Company[];
  total: number;
}

/** KPI counts returned by GET /companies/stats. */
export interface CompanyStats {
  total: number;
  active: number;
  /** Submitted applications awaiting review. Excludes drafts. */
  pending: number;
  /** Self-registered companies still working through the onboarding wizard. */
  onboarding: number;
  suspended: number;
  blacklisted: number;
  /** Approved customers whose submitted profile edits are awaiting review. */
  pendingChanges: number;
}

/* ------------------------------------------------------------------ *
 * Related data shown on the customer detail page (mocked for now).   *
 * ------------------------------------------------------------------ */

export type CustomerBookingStatus =
  | "DRAFT"
  | "SUBMITTED"
  | "PENDING_APPROVAL"
  | "APPROVED"
  | "PAID"
  | "IN_TRANSIT"
  | "ARRIVED"
  | "COMPLETED"
  | "REJECTED"
  | "CANCELLED";

export interface CustomerBooking {
  id: string;
  reference: string;
  status: CustomerBookingStatus;
  tradeDirection: "IMPORT" | "EXPORT";
  freightType: "CONTAINER" | "BULK";
  originLabel: string;
  destinationLabel: string;
  totalAmount: number;
  currency: "ETB" | "USD";
  scheduledDate?: string | null;
  createdAt: string;
}

export interface CustomerDocument {
  id: string;
  name: string;
  /** File-upload setting code, e.g. "business_license", "contract". */
  code: string;
  mimeType: string;
  /** Size in bytes. */
  size: number;
  uploadedAt: string;
  url?: string | null;
  /**
   * Reviewer verdict. `change_requested` means the customer has been asked to
   * re-upload a corrected version and the role cannot be approved until they do;
   * `null` means nobody has reviewed this document.
   */
  reviewStatus?: "change_requested" | "approved" | null;
  /** The reviewer's reason, shown to the customer verbatim. */
  reviewNote?: string | null;
  reviewedAt?: string | null;
}

export type CustomerPaymentStatus =
  | "action-required"
  | "processing"
  | "success"
  | "failed"
  | "canceled"
  | "refunded";

export type CustomerPaymentMethod =
  | "telebirr"
  | "cbe-birr"
  | "ebirr"
  | "waafi"
  | "card"
  | "dmoney"
  | "cac-bank";

export interface CustomerPayment {
  id: string;
  reference: string;
  /** Booking reference the payment settles. */
  bookingReference: string;
  amount: number;
  currency: "ETB" | "USD";
  method: CustomerPaymentMethod;
  status: CustomerPaymentStatus;
  paidAt?: string | null;
  createdAt: string;
}
