scalar DateTime
scalar JSON

enum UserRole {
  CLIENT
  MANAGER
  SUPER_MANAGER
}

enum MessengerType {
  TELEGRAM
  MAX
}

enum LoginChannel {
  EMAIL
  TELEGRAM
  MAX
}

enum RegistrationStatus {
  PENDING
  APPROVED
  REJECTED
}

enum OrderKind {
  READY
  CALCULATION
}

enum OrderStatus {
  NEW
  MANAGER_PROCESSING
  WAITING_DOUBLE_CONFIRM
  CLIENT_REJECTED
  MANAGER_REJECTED
  MANAGER_BLOCKED
  CONFIRMED
  IN_PROGRESS
  COMPLETED
}

enum WithdrawalStatus {
  PENDING
  APPROVED
  REJECTED
}

enum Decision {
  APPROVE
  REJECT
}

type Company {
  id: ID!
  name: String!
  inn: String
}

type User {
  id: ID!
  email: String!
  fullName: String!
  role: UserRole!
  company: Company
}

type CounterpartyProfile {
  id: ID!
  userId: ID!
  companyName: String!
  companyFullName: String!
  inn: String!
  kpp: String
  ogrn: String
  legalAddress: String!
  bankName: String!
  bik: String!
  correspondentAccount: String!
  checkingAccount: String!
  signerFullName: String!
  signerPosition: String!
  signerBasis: String!
  isComplete: Boolean!
  createdAt: DateTime!
  updatedAt: DateTime!
}

type DeliveryAddress {
  id: ID!
  userId: ID!
  label: String
  address: String!
  unrestrictedValue: String
  fiasId: String
  isDefault: Boolean!
  createdAt: DateTime!
  updatedAt: DateTime!
}

type AuthCodeRequestResult {
  challengeToken: String!
  channel: LoginChannel!
  destination: String!
  expiresAt: DateTime!
}

type AuthSession {
  accessToken: String!
  expiresAt: DateTime!
  user: User!
}

type Invitation {
  id: ID!
  token: String!
  email: String!
  companyName: String!
  managerId: ID!
  acceptedById: ID
  expiresAt: DateTime!
  acceptedAt: DateTime
  createdAt: DateTime!
}

type RegistrationRequest {
  id: ID!
  companyName: String!
  inn: String
  contactName: String!
  email: String!
  status: RegistrationStatus!
  rejectionReason: String
  reviewedById: ID
  createdAt: DateTime!
  updatedAt: DateTime!
}

type ManagerUser {
  id: ID!
  email: String!
  fullName: String!
  role: UserRole!
  companyName: String
  inn: String
  createdAt: DateTime!
  orderCount: Int!
  lastOrderAt: DateTime
  telegramConnection: MessengerConnection
}

type MessengerConnection {
  id: ID!
  userId: ID!
  type: MessengerType!
  channelId: String!
  displayName: String
  username: String
  avatarAvailable: Boolean!
  isActive: Boolean!
}

type MessengerDispatchResult {
  type: MessengerType!
  channelId: String!
  success: Boolean!
  detail: String!
  sentAt: DateTime!
}

type NotificationHistoryItem {
  id: ID!
  channel: MessengerType!
  title: String!
  message: String!
  createdAt: DateTime!
  orderId: ID
}

type NotificationTemplateChannel {
  channel: LoginChannel!
  implemented: Boolean!
  subject: String
  body: [String!]!
  buttonText: String
  buttonUrl: String
}

type NotificationTemplate {
  id: ID!
  title: String!
  channels: [NotificationTemplateChannel!]!
}

type IntegrationSyncItem {
  id: ID!
  title: String!
  description: String!
  source: String!
  syncedCount: Int!
  lastSyncedAt: DateTime
  status: String!
  note: String!
}

type IntegrationSyncDashboard {
  generatedAt: DateTime!
  lastActivityAt: DateTime
  totalOrders: Int!
  totalProducts: Int!
  totalClients: Int!
  items: [IntegrationSyncItem!]!
}

type BonusProgramLink {
  userId: ID!
  token: String!
  url: String!
  expiresAt: DateTime!
}

type Warehouse {
  id: ID!
  code: String!
  name: String!
}

type ProductWarehouseBalance {
  warehouse: Warehouse!
  availableQty: Float!
}

type Product {
  id: ID!
  sku: String!
  name: String!
  description: String
  productType: String
  widthMm: Int
  lengthM: Int
  thicknessMicron: Int
  sleeveBrand: String
  quantityPerBox: String
  tags: [String!]!
  isCustomizable: Boolean!
  isActive: Boolean!
  availableInWarehouses: [ProductWarehouseBalance!]!
}

type CatalogProductTypeSetting {
  productType: String!
  showQuantityPerBox: Boolean!
  allowCustomLength: Boolean!
  customLengthMinM: Int
  customLengthMaxM: Int
  customLengthStepM: Int
  allowCustomSleeveBrand: Boolean!
  allowCustomLabel: Boolean!
  widthOptionsMm: [Int!]!
  lengthOptionsM: [Int!]!
  thicknessOptionsMicron: [Int!]!
  sleeveOptions: [String!]!
  colorOptions: [String!]!
  labelOptions: [String!]!
}

type CartItem {
  id: ID!
  productId: ID!
  productName: String!
  sku: String!
  isCustomizable: Boolean!
  quantity: Float!
  parameters: JSON!
  createdAt: DateTime!
  updatedAt: DateTime!
}

type Cart {
  id: ID!
  userId: ID!
  deliveryAddressId: ID
  deliveryAddress: DeliveryAddress
  items: [CartItem!]!
  createdAt: DateTime!
  updatedAt: DateTime!
}

type OrderItem {
  id: ID!
  productId: ID
  productName: String!
  quantity: Float!
  unitPrice: Float
  lineTotal: Float
}

type OrderStatusEvent {
  id: ID!
  status: OrderStatus!
  actorUserId: ID!
  note: String
  createdAt: DateTime!
}

type Order {
  id: ID!
  code: String!
  kind: OrderKind!
  status: OrderStatus!
  customerId: ID!
  deliveryAddress: String
  managerId: ID
  clientApproved: Boolean
  managerApproved: Boolean
  blockReason: String
  deliveryTerms: String
  deliveryFee: Float
  totalPrice: Float
  calculationPayload: JSON
  items: [OrderItem!]!
  history: [OrderStatusEvent!]!
  createdAt: DateTime!
  updatedAt: DateTime!
}

type ReferralLink {
  id: ID!
  referrerId: ID!
  refereeId: ID!
  createdById: ID!
  bonusPercent: Float!
  createdAt: DateTime!
}

type ManagerReferralLink {
  id: ID!
  referrerId: ID!
  referrerName: String!
  referrerEmail: String!
  referrerCompanyName: String
  refereeId: ID!
  refereeName: String!
  refereeEmail: String!
  refereeCompanyName: String
  createdById: ID!
  bonusPercent: Float!
  createdAt: DateTime!
}

type BonusTransaction {
  id: ID!
  userId: ID!
  amount: Float!
  reason: String!
  orderId: ID
  createdAt: DateTime!
}

type RewardWithdrawalRequest {
  id: ID!
  requesterId: ID!
  amount: Float!
  status: WithdrawalStatus!
  reviewedById: ID
  reviewComment: String
  createdAt: DateTime!
  updatedAt: DateTime!
}

type ReferralStats {
  referrerId: ID!
  availableBalance: Float!
  referralsCount: Int!
  transactions: [BonusTransaction!]!
  pendingWithdrawals: [RewardWithdrawalRequest!]!
}

type ManagerBonusBalance {
  userId: ID!
  email: String!
  fullName: String!
  companyName: String
  balance: Float!
  pendingWithdrawalAmount: Float!
  transactionsCount: Int!
}

type ManagerBonusAccount {
  userId: ID!
  email: String!
  fullName: String!
  companyName: String
  balance: Float!
  earnedAmount: Float!
  pendingWithdrawalAmount: Float!
  transactionsCount: Int!
  referralsCount: Int!
  referralLinks: [ManagerReferralLink!]!
  transactions: [BonusTransaction!]!
  pendingWithdrawals: [RewardWithdrawalRequest!]!
}

type ManagerWithdrawalRequest {
  id: ID!
  requesterId: ID!
  requesterEmail: String!
  requesterFullName: String!
  companyName: String
  amount: Float!
  status: WithdrawalStatus!
  reviewedById: ID
  reviewComment: String
  createdAt: DateTime!
  updatedAt: DateTime!
}

type Query {
  healthcheck: String!
  me: User
  myCounterpartyProfile: CounterpartyProfile
  myCart: Cart!
  myDeliveryAddresses: [DeliveryAddress!]!
  myMessengerConnections: [MessengerConnection!]!
  myNotificationHistory(channel: MessengerType!, limit: Int = 50): [NotificationHistoryItem!]!
  notificationTemplates: [NotificationTemplate!]!
  integrationSyncDashboard: IntegrationSyncDashboard!
  managerNotificationHistory(userId: ID!, channel: MessengerType!, limit: Int = 50): [NotificationHistoryItem!]!
  clientProducts: [Product!]!
  catalogProductTypeSettings: [CatalogProductTypeSetting!]!
  order(id: ID!): Order
  myOrders: [Order!]!
  myCurrentOrders: [Order!]!
  managerUsers: [ManagerUser!]!
  managerOrders(status: OrderStatus, customerId: ID): [Order!]!
  managerReferralLinks: [ManagerReferralLink!]!
  managerBonusBalances: [ManagerBonusBalance!]!
  managerBonusAccount(userId: ID!): ManagerBonusAccount!
  managerWithdrawalRequests(status: WithdrawalStatus): [ManagerWithdrawalRequest!]!
  registrationRequests(status: RegistrationStatus): [RegistrationRequest!]!
  referralStats: ReferralStats!
}

input RequestLoginCodeInput {
  channel: LoginChannel!
  destination: String!
}

input VerifyLoginCodeInput {
  challengeToken: String!
  code: String!
}

input RegisterSelfInput {
  companyName: String!
  inn: String
  contactName: String!
  email: String!
}

input ReviewRegistrationRequestInput {
  requestId: ID!
  decision: Decision!
  rejectionReason: String
}

input CreateInvitationInput {
  email: String!
  companyName: String!
  expiresInDays: Int = 7
}

input AcceptInvitationInput {
  token: String!
  fullName: String!
}

input ConnectMessengerInput {
  type: MessengerType!
  channelId: String!
}

input UpsertMyCounterpartyProfileInput {
  companyName: String!
  companyFullName: String!
  inn: String!
  kpp: String
  ogrn: String
  legalAddress: String!
  bankName: String!
  bik: String!
  correspondentAccount: String!
  checkingAccount: String!
  signerFullName: String!
  signerPosition: String!
  signerBasis: String!
}

input CreateMyDeliveryAddressInput {
  label: String
  address: String!
  unrestrictedValue: String
  fiasId: String
}

input UpdateCartItemQuantityInput {
  productId: ID!
  quantity: Float!
}

input UpsertCatalogProductTypeSettingInput {
  productType: String!
  showQuantityPerBox: Boolean!
  allowCustomLength: Boolean!
  customLengthMinM: Int
  customLengthMaxM: Int
  customLengthStepM: Int
  allowCustomSleeveBrand: Boolean!
  allowCustomLabel: Boolean!
  widthOptionsMm: [Int!]!
  lengthOptionsM: [Int!]!
  thicknessOptionsMicron: [Int!]!
  sleeveOptions: [String!]!
  colorOptions: [String!]!
  labelOptions: [String!]!
}

input ReadyOrderItemInput {
  productId: ID!
  quantity: Float!
}

input SubmitReadyOrderInput {
  items: [ReadyOrderItemInput!]!
  deliveryAddressId: ID
}

input SubmitCalculationOrderInput {
  productName: String!
  quantity: Float!
  parameters: JSON!
  deliveryAddressId: ID
}

input SetOrderOfferInput {
  orderId: ID!
  itemPrices: [OrderItemPriceInput!]!
  deliveryTerms: String!
  deliveryFee: Float
}

input OrderItemPriceInput {
  itemId: ID!
  unitPrice: Float
}

input CreateReferralInput {
  referrerUserId: ID!
  refereeUserId: ID!
  bonusPercent: Float!
}

input AddBonusTransactionInput {
  userId: ID!
  amount: Float!
  reason: String!
  orderId: ID
}

input RequestRewardWithdrawalInput {
  amount: Float!
}

input ReviewRewardWithdrawalInput {
  withdrawalId: ID!
  decision: Decision!
  reviewComment: String
}

type Mutation {
  requestLoginCode(input: RequestLoginCodeInput!): AuthCodeRequestResult!
  verifyLoginCode(input: VerifyLoginCodeInput!): AuthSession!
  consumeLoginToken(token: String!): AuthSession!
  registerSelf(input: RegisterSelfInput!): RegistrationRequest!
  reviewRegistrationRequest(input: ReviewRegistrationRequestInput!): RegistrationRequest!
  createInvitation(input: CreateInvitationInput!): Invitation!
  acceptInvitation(input: AcceptInvitationInput!): User!
  connectMessenger(input: ConnectMessengerInput!): MessengerConnection!
  deleteMyMessengerConnection(connectionId: ID!): Boolean!
  upsertMyCounterpartyProfile(input: UpsertMyCounterpartyProfileInput!): CounterpartyProfile!
  upsertCatalogProductTypeSetting(input: UpsertCatalogProductTypeSettingInput!): CatalogProductTypeSetting!
  addProductToCart(productId: ID!): Cart!
  updateCartItemQuantity(input: UpdateCartItemQuantityInput!): Cart!
  removeCartItem(productId: ID!): Cart!
  setCartDeliveryAddress(addressId: ID): Cart!
  clearCart: Cart!
  createMyDeliveryAddress(input: CreateMyDeliveryAddressInput!): DeliveryAddress!
  setMyDefaultDeliveryAddress(addressId: ID!): DeliveryAddress!
  deleteMyDeliveryAddress(addressId: ID!): Boolean!
  sendTestMessengerMessage(type: MessengerType!, channelId: String, message: String): MessengerDispatchResult!

  submitReadyOrder(input: SubmitReadyOrderInput!): Order!
  submitCalculationOrder(input: SubmitCalculationOrderInput!): Order!
  managerSetOrderOffer(input: SetOrderOfferInput!): Order!
  managerSetOrderStatus(orderId: ID!, status: OrderStatus!): Order!
  clientReviewOrder(orderId: ID!, decision: Decision!): Order!

  createReferral(input: CreateReferralInput!): ReferralLink!
  createBonusProgramLink(userId: ID!): BonusProgramLink!
  addBonusTransaction(input: AddBonusTransactionInput!): BonusTransaction!
  requestRewardWithdrawal(input: RequestRewardWithdrawalInput!): RewardWithdrawalRequest!
  reviewRewardWithdrawal(input: ReviewRewardWithdrawalInput!): RewardWithdrawalRequest!
}
