"""Lifecycle status of a project transfer job (and of each product within it)."""
enum ProjectTransferJobStatus {
    """Job has been created and is waiting to be picked up for processing."""
    QUEUED
    """Step Functions execution is in flight; products are being moved."""
    PROCESSING
    """All products in the job transferred successfully."""
    COMPLETED
    """The job (or one of its products) failed; see failureReason."""
    FAILED
    """Job was soft-deleted before processing began."""
    DELETED
}

"""A job representing the transfer of a project's products between vendor accounts."""
type ProjectTransferJob {
    """When the job was created."""
    createdAt: DateTime!
    """The identity that created the job."""
    createdBy: Identity!
    """The label (vendor or subaccount) that products are being transferred to."""
    destinationLabel: Label!
    """Reason the job failed; populated when status is FAILED."""
    failureReason: String
    """When the job's state last changed."""
    lastUpdatedAt: DateTime
    """The label (vendor or subaccount) that products are being transferred from."""
    originLabel: Label!
    """Per-product transfer records that make up this job."""
    products: [ProductTransferJob!]!
    """The project being transferred."""
    project: Project!
    """The project_code at the time the job was created."""
    projectCode: String @deprecated(reason: "Never populated — always null. Will be removed in a future release.")
    """The transfer job ID."""
    projectTransferJobId: ID!
    """Statement period cut-off; revenue earned on or before this date stays with the originator."""
    revenueCutoffDate: DateTime
    """Lifecycle status of the job."""
    status: ProjectTransferJobStatus!
    """When the transfer of all products in this job finished successfully; populated when status is COMPLETED."""
    transferCompletedOn: DateTime
}

"""A single product's transfer record within a project transfer job."""
type ProductTransferJob {
    """Reason this product's transfer failed; populated by the transfer SFN."""
    failureReason: String
    """The product being transferred. Populated from snapshot data for soft-deleted products."""
    product: Product!
    """The product transfer history row ID."""
    productTransferHistoryId: ID!
    """The parent transfer job ID."""
    projectTransferJobId: ID!
    """Lifecycle status of this product's transfer; populated by the transfer SFN."""
    status: ProjectTransferJobStatus
    """When this product's transfer completed successfully; populated by the transfer SFN."""
    transferCompletedOn: DateTime
}

"""A page of project transfer jobs (offset/limit pagination)."""
type ProjectTransferJobsPage {
    """The transfer jobs on this page."""
    items: [ProjectTransferJob!]!
    """Total number of jobs matching the query, ignoring pagination."""
    totalCount: Int!
}

"""Typed error returned by createProjectTransferJob when the request cannot be queued for a known business reason (invalid input, project not eligible, etc.). Clients should branch on this in the response union instead of catching a thrown GraphQL error."""
type CreateProjectTransferJobError {
    """Stable machine-readable code identifying the failure category."""
    code: String!
    """Human-readable message safe to surface to end users."""
    message: String!
}

"""Result of createProjectTransferJob: either the newly queued job or a typed error describing why it could not be queued."""
union CreateProjectTransferJobResponse =
    | ProjectTransferJob
    | CreateProjectTransferJobError

"""Typed error returned by deleteProjectTransferJob when the job cannot be deleted (e.g. not in QUEUED status)."""
type DeleteProjectTransferJobError {
    """Stable machine-readable code identifying the failure category."""
    code: String!
    """Human-readable message safe to surface to end users."""
    message: String!
}

"""Result of deleteProjectTransferJob: true on success or a typed error describing why it could not be deleted."""
union DeleteProjectTransferJobResponse =
    | DeleteProjectTransferJobSuccess
    | DeleteProjectTransferJobError

"""Returned by deleteProjectTransferJob when the job was successfully soft-deleted."""
type DeleteProjectTransferJobSuccess {
    jobId: ID!
}

"""Conditions filter within a transfer term condition."""
input TransferTermConditionsInput {
    countries: [String!]
    stores: [String!]
    transactionTypes: [String!]
}

"""A single rate condition within a transfer term."""
input TransferTermConditionInput {
    priority: Int!
    termRate: String!
    commission: String
    name: String
    conditions: TransferTermConditionsInput
}

"""Label/product/contributor scoping for a transfer term's attachments."""
input TransferTermAttachmentRelationsInput {
    labelIds: [String!]
    upcs: [String!]
    contributors: [String!]
}

"""A transfer term to stage against the destination contract."""
input TransferTermInput {
    contractId: ID!
    """One of: label, track, product, artist, catalog."""
    termType: String!
    name: String
    attachments: [ID!]
    attachmentRelations: TransferTermAttachmentRelationsInput
    conditions: [TransferTermConditionInput!]!
}

"""Fields required to create a new project transfer job."""
input ProjectTransferJobInput {
    """Subaccount the products are moving into; omit for a vendor-level destination."""
    destinationSubaccountId: ID
    """Vendor the products are moving into."""
    destinationVendorId: ID!
    """Subaccount the products are moving out of; omit for a vendor-level origin."""
    originSubaccountId: ID
    """Vendor the products are moving out of."""
    originVendorId: ID!
    """The project whose products are being transferred."""
    projectId: ID!
    """No longer used. The server computes revenue_cutoff_date as the last day of the previous month. This field is accepted for backwards compatibility but silently ignored."""
    revenueCutoffDate: String @deprecated(reason: "Server computes this automatically. Sending a value has no effect.")
}

extend type Query {
    """Fetch a single project transfer job by ID, including its product records. Returns null when the job does not exist or has been soft-deleted."""
    projectTransferJob(jobId: ID!): ProjectTransferJob
    """Fetch a page of project transfer jobs. All filters are optional; null means 'no filter' for that field. When called with no filters, returns transfer jobs the caller has access to in `created_at DESC` order, paginated by `limit`/`offset`. `limit` is capped server-side at 100."""
    projectTransferJobs(
        destinationVendorId: ID
        limit: Int = 25
        offset: Int = 0
        originVendorId: ID
        projectId: ID
        status: ProjectTransferJobStatus
    ): ProjectTransferJobsPage!
}

extend type Mutation {
    """Create a new project transfer job to move products between vendor accounts. The server resolves products from the project at execution time. Returns a union so clients can branch on success vs typed business errors without try/catch."""
    createProjectTransferJob(
        input: ProjectTransferJobInput!
    ): CreateProjectTransferJobResponse!
    """Create a project transfer job and stage its terms in a single operation. Terms are required. Returns the newly created job on success or a typed error on failure."""
    createProjectTransfer(
        input: ProjectTransferJobInput!
        terms: [TransferTermInput!]!
    ): CreateProjectTransferJobResponse!
    """Soft-delete a QUEUED transfer job. Returns the deleted job ID on success or a typed error if the job cannot be deleted."""
    deleteProjectTransferJob(jobId: ID!): DeleteProjectTransferJobResponse!
}
