extend type Query {
    users(
        text: String @where(operator: "like", key: "name")
        orderBy: _
            @orderBy(
                columns: ["updated_at", "created_at", "name", "is_active", "id"]
            )
    ): [User!]! @paginate(defaultCount: 10) @can(ability: "super_admin")
    user(id: ID @eq): User @find @can(ability: "super_admin")
    me: User @ensureEmailIsVerified @field(resolver: "UserQuery@me")
    downloads: [OrderedFile]
        @paginate(
            builder: "Marvel\\GraphQL\\Queries\\UserQuery@fetchDownloadableFiles"
            defaultCount: 15
        )
    usersByPermission(
        searchJoin: String = "AND"
        orderBy: String
        sortedBy: String
        search: String
        is_active: Boolean
        permission: String!
        shop_id: String
        exclude: String
    ): [User]!
        @paginate(
            builder: "Marvel\\GraphQL\\Queries\\UserQuery@fetchUsersByPermission"
            defaultCount: 15
        )
    myStaffs(
        searchJoin: String
        orderBy: String
        sortedBy: String
        search: String
    ): [User]!
        @paginate(
            builder: "Marvel\\GraphQL\\Queries\\UserQuery@fetchMyStaffs"
            defaultCount: 15
        )
}

type User {
    id: ID
    name: String
    email: String
    shop_id: ID
    created_at: DateTime
    updated_at: DateTime
    profile: Profile @hasOne
    permissions: [UserPermission] @morphMany
    wallet: Wallet @hasOne
    shops: [Shop] @hasMany
    refunds: [Refund] @hasMany
    managed_shop: Shop @belongsTo
    is_active: Boolean
    address: [Address] @hasMany
    orders: [Order] @hasMany @lazyLoad(relations: ["products", "status"])
    last_order: Order
}

type UserPermission @model(class: "Spatie\\Permission\\Models\\Permission") {
    id: ID!
    name: String
}

type Wallet {
    id: ID!
    total_points: Int
    points_used: Int
    available_points: Int
    created_at: DateTime
    updated_at: DateTime
}

input LoginInput {
    email: String!
    password: String!
}

input SocialLoginInput {
    provider: String
    access_token: String
}

input OtpInput {
    phone_number: String!
}

input VerifyOtpInput {
    otp_id: String!
    code: String!
    phone_number: String!
}

input OtpLoginInput {
    otp_id: String!
    code: String!
    phone_number: String!
    name: String
    email: String
}

input UpdateContactInput {
    otp_id: String!
    code: String!
    phone_number: String!
    user_id: String!
}

input RegisterInput {
    email: String!
        @rules(
            apply: ["unique:users,email"]
            messages: { unique: "Sorry! this email has been already taken." }
        )
    password: String!
    name: String!
    permission: Permission
}

type AuthResponse {
    token: String
    permissions: [String]
    role: String
}

type OtpResponse {
    message: String
    success: Boolean
    provider: String
    id: String
    phone_number: String
    is_contact_exist: Boolean
}

type OrderedFile {
    id: ID!
    purchase_key: String!
    digital_file_id: ID!
    customer_id: ID!
    file: DigitalFile @hasOne
    order: Order
    tracking_number: String
    created_at: DateTime
    updated_at: DateTime
}

input NotificationsInput {
    email: String
    enable: Boolean
}

input UserProfileInput {
    notifications: NotificationsInput
    avatar: AttachmentInput
    bio: String
    socials: [SocialInput]
    contact: String
    id: ID
}

input ProfileHasOne {
    upsert: UserProfileInput
}

input UserAddressUpsertInput {
    title: String!
    default: Boolean
    address: UserAddressInput!
    location: GoogleMapLocationInput
    type: AddressType!
    id: ID
}

input AddressHasMany {
    upsert: [UserAddressUpsertInput]
}

input UpdateUserInput {
    id: ID!
    name: String
    profile: ProfileHasOne
    address: AddressHasMany
}

input ChangePasswordInput {
    oldPassword: String!
    newPassword: String!
}

input ForgetPasswordInput {
    email: String!
}
input VerifyForgetPasswordTokenInput {
    token: String!
    email: String!
}

input ResetPasswordInput {
    token: String!
    email: String!
    password: String!
}

type PasswordChangeResponse {
    message: String
    success: Boolean
}

type SuccessResponse {
    message: String
    success: Boolean
}

input AddPointsInput {
    points: Int!
    customer_id: ID!
        @rules(
            apply: ["required", "exists:users,id"]
            messages: { exists: "Sorry! The customer doesn't exists." }
        )
}
input UpdateEmailUserInput {
    email: String
}

input MakeOrRevokeAdminInput {
    user_id: ID!
        @rules(
            apply: ["required", "exists:users,id"]
            messages: { exists: "Sorry! The user doesn't exists." }
        )
}

input GenerateDownloadableUrlInput {
    digital_file_id: ID!
        @rules(
            apply: ["required", "exists:digital_files,id"]
            messages: { exists: "Sorry! The file doesn't exists." }
        )
}

extend type Mutation {
    login(input: LoginInput! @spread): AuthResponse
        @field(resolver: "AuthMutator@token")
    socialLogin(input: SocialLoginInput! @spread): AuthResponse
        @field(resolver: "AuthMutator@socialLogin")
    sendOtpCode(input: OtpInput! @spread): OtpResponse
        @field(resolver: "AuthMutator@sendOtpCode")
    verifyOtpCode(input: VerifyOtpInput! @spread): SuccessResponse
        @field(resolver: "AuthMutator@verifyOtpCode")
    otpLogin(input: OtpLoginInput! @spread): AuthResponse
        @field(resolver: "AuthMutator@otpLogin")
    updateContact(input: UpdateContactInput! @spread): SuccessResponse
        @field(resolver: "AuthMutator@updateContact")
    logout: Boolean @field(resolver: "AuthMutator@logout")
    register(input: RegisterInput! @spread): AuthResponse
        @field(resolver: "AuthMutator@register")
    banUser(id: ID!): User @field(resolver: "AuthMutator@banUser")
    activeUser(id: ID!): User @field(resolver: "AuthMutator@activeUser")
    changePassword(input: ChangePasswordInput! @spread): PasswordChangeResponse
        @field(resolver: "AuthMutator@changePassword")
    forgetPassword(input: ForgetPasswordInput! @spread): PasswordChangeResponse
        @field(resolver: "AuthMutator@forgetPassword")
    verifyForgetPasswordToken(
        input: VerifyForgetPasswordTokenInput! @spread
    ): PasswordChangeResponse
        @field(resolver: "AuthMutator@verifyForgetPasswordToken")
    resetPassword(input: ResetPasswordInput! @spread): PasswordChangeResponse
        @field(resolver: "AuthMutator@resetPassword")
    register(input: RegisterInput! @spread): AuthResponse
        @field(resolver: "AuthMutator@register")
    addPoints(input: AddPointsInput! @spread): Boolean
        @field(resolver: "AuthMutator@addPoints")
    updateUser(input: UpdateUserInput! @spread): User
        @update
        @can(ability: "customer")
    makeOrRevokeAdmin(input: MakeOrRevokeAdminInput! @spread): Boolean
        @field(resolver: "AuthMutator@makeOrRevokeAdmin")
    generateDownloadableUrl(
        input: GenerateDownloadableUrlInput! @spread
    ): String @field(resolver: "AuthMutator@generateDownloadableUrl")
    subscribeToNewsletter(email: String!): Boolean
        @field(resolver: "AuthMutator@subscribeToNewsletter")
    updateUserEmail(input: UpdateEmailUserInput! @spread): SuccessResponse
        @field(resolver: "AuthMutator@updateUserEmail")
    resendVerificationEmail: SuccessResponse!
        @field(resolver: "AuthMutator@resendVerificationEmail")
    licenseKeyValidation(license_key: String!): Boolean
        @field(resolver: "AuthMutator@licenseVerification")
}
