import type {
  BillingStats,
  BillingOptions,
  BillingSettings,
  BillingClientRow,
  BillingClientDetail,
  BillingActionResult,
  UpdateBillingConfigPayload,
  UpdateBillingSettingsPayload,
  DirectDebitMandateState,
  BillingProduct,
  BillingProductPayload,
  BillingProfile,
  BillingProfilePayload,
  PennylaneCustomer,
  PennylaneLinkState,
  VehiclePlansState,
  UpdateVehiclePlansPayload,
  PlanPricePayload,
} from "@/domain/entities/billing";
import type { BackendPaginatedData, PaginationQueryParams } from "@/shared/types";

export interface BillingRepository {
  getStats(): Promise<BillingStats>;
  getOptions(): Promise<BillingOptions>;
  getSettings(): Promise<BillingSettings>;
  updateSettings(payload: UpdateBillingSettingsPayload): Promise<BillingSettings>;

  /** The products the contract clients are invoiced; each call returns the whole list. */
  getProducts(): Promise<BillingProduct[]>;
  createProduct(payload: BillingProductPayload): Promise<BillingProduct[]>;
  updateProduct(productId: number, payload: BillingProductPayload): Promise<BillingProduct[]>;

  findClients(params: PaginationQueryParams): Promise<BackendPaginatedData<BillingClientRow>>;
  findClient(clientId: number): Promise<BillingClientDetail>;
  updateClientConfig(
    clientId: number,
    payload: UpdateBillingConfigPayload
  ): Promise<BillingClientDetail>;

  /** Force-lock (lock_override = locked). Blocks app access regardless of tolerance. */
  suspendClient(clientId: number): Promise<BillingActionResult>;
  /** Force-unlock (lock_override = unlocked). Restores access even if still unpaid. */
  reactivateClient(clientId: number): Promise<BillingActionResult>;

  /** Reconcile an off-card (Virement) invoice as paid. */
  markInvoicePaid(invoiceId: number): Promise<BillingActionResult>;

  /** The client's SEPA mandate, read back from Pennylane on each call. */
  getMandate(clientId: number): Promise<DirectDebitMandateState>;
  /** Pennylane e-mails the client the mandate to sign. */
  requestMandate(clientId: number): Promise<DirectDebitMandateState>;

  /** What the client is invoiced and at what price, with last month's and this month's invoice. */
  getProfile(clientId: number): Promise<BillingProfilePayload>;
  updateProfile(clientId: number, profile: Omit<BillingProfile, "updated_at">): Promise<BillingProfilePayload>;

  /** The Pennylane customer the client's invoices go to, as Pennylane has it. */
  getPennylaneLink(clientId: number): Promise<PennylaneLinkState>;
  /** Pennylane customers by name (starting with) or SIREN / SIRET. */
  searchPennylaneCustomers(query: string): Promise<PennylaneCustomer[]>;
  /** Links the client to that customer (checked to exist); null unlinks. */
  updatePennylaneLink(clientId: number, customerId: number | null): Promise<PennylaneLinkState>;

  /** Plans per vehicle: the client's vehicles with their plans, its prices per plan. */
  getVehiclePlans(clientId: number): Promise<VehiclePlansState>;
  /** Adds and takes off plans on the chosen vehicles. */
  updateVehiclePlans(clientId: number, payload: UpdateVehiclePlansPayload): Promise<VehiclePlansState>;
  /** The client's own prices per plan; null goes back to the list price. */
  updatePlanPrices(clientId: number, prices: PlanPricePayload[]): Promise<VehiclePlansState>;
}
