/**
 * This code was GENERATED using the codama library.
 * Please DO NOT EDIT THIS FILE, instead use visitors
 * to add features, then rerun codama to update it.
 *
 * @see https://github.com/codama-idl/codama
 */

import {
  assertAccountExists,
  assertAccountsExist,
  decodeAccount,
  fetchEncodedAccount,
  fetchEncodedAccounts,
  type Account,
  type EncodedAccount,
  type FetchAccountConfig,
  type FetchAccountsConfig,
  type MaybeAccount,
  type MaybeEncodedAccount,
} from '@solana/accounts';
import {
  getAddressDecoder,
  getAddressEncoder,
  type Address,
} from '@solana/addresses';
import {
  addDecoderSizePrefix,
  addEncoderSizePrefix,
  combineCodec,
  fixDecoderSize,
  fixEncoderSize,
  getBytesDecoder,
  getBytesEncoder,
  getI64Decoder,
  getI64Encoder,
  getStructDecoder,
  getStructEncoder,
  getU32Decoder,
  getU32Encoder,
  getU64Decoder,
  getU64Encoder,
  getU8Decoder,
  getU8Encoder,
  getUtf8Decoder,
  getUtf8Encoder,
  transformEncoder,
  type Codec,
  type Decoder,
  type Encoder,
  type ReadonlyUint8Array,
} from '@solana/codecs';

export const WORK_ORDER_ACCOUNT_DISCRIMINATOR = new Uint8Array([
  145, 22, 187, 234, 88, 192, 115, 77,
]);

export function getWorkOrderAccountDiscriminatorBytes() {
  return fixEncoderSize(getBytesEncoder(), 8).encode(
    WORK_ORDER_ACCOUNT_DISCRIMINATOR
  );
}

export type WorkOrderAccount = {
  discriminator: ReadonlyUint8Array;
  orderId: bigint;
  client: Address;
  provider: Address;
  title: string;
  description: string;
  requirements: string[];
  paymentAmount: bigint;
  paymentToken: Address;
  deadline: bigint;
  status: WorkOrderStatus;
  createdAt: bigint;
  updatedAt: bigint;
  deliverables: ReadonlyUint8Array;
  bump: number;
  reserved: ReadonlyUint8Array;
};

export type WorkOrderAccountArgs = {
  orderId: number | bigint;
  client: Address;
  provider: Address;
  title: string;
  description: string;
  requirements: string[];
  paymentAmount: number | bigint;
  paymentToken: Address;
  deadline: number | bigint;
  status: WorkOrderStatus;
  createdAt: number | bigint;
  updatedAt: number | bigint;
  deliverables: ReadonlyUint8Array;
  bump: number;
  reserved: ReadonlyUint8Array;
};

export enum WorkOrderStatus {
  Pending = 0,
  InProgress = 1,
  Completed = 2,
  Cancelled = 3,
  Disputed = 4,
}

export function getWorkOrderAccountEncoder(): Encoder<WorkOrderAccountArgs> {
  return transformEncoder(
    getStructEncoder([
      ['discriminator', fixEncoderSize(getBytesEncoder(), 8)],
      ['orderId', getU64Encoder()],
      ['client', getAddressEncoder()],
      ['provider', getAddressEncoder()],
      ['title', addEncoderSizePrefix(getUtf8Encoder(), getU32Encoder())],
      ['description', addEncoderSizePrefix(getUtf8Encoder(), getU32Encoder())],
      ['requirements', addEncoderSizePrefix(getUtf8Encoder(), getU32Encoder())],
      ['paymentAmount', getU64Encoder()],
      ['paymentToken', getAddressEncoder()],
      ['deadline', getI64Encoder()],
      ['status', getU8Encoder()],
      ['createdAt', getI64Encoder()],
      ['updatedAt', getI64Encoder()],
      ['deliverables', fixEncoderSize(getBytesEncoder(), 128)],
      ['bump', getU8Encoder()],
      ['reserved', fixEncoderSize(getBytesEncoder(), 31)],
    ]),
    (value) => ({ ...value, discriminator: WORK_ORDER_ACCOUNT_DISCRIMINATOR })
  );
}

export function getWorkOrderAccountDecoder(): Decoder<WorkOrderAccount> {
  return getStructDecoder([
    ['discriminator', fixDecoderSize(getBytesDecoder(), 8)],
    ['orderId', getU64Decoder()],
    ['client', getAddressDecoder()],
    ['provider', getAddressDecoder()],
    ['title', addDecoderSizePrefix(getUtf8Decoder(), getU32Decoder())],
    ['description', addDecoderSizePrefix(getUtf8Decoder(), getU32Decoder())],
    ['requirements', addDecoderSizePrefix(getUtf8Decoder(), getU32Decoder())],
    ['paymentAmount', getU64Decoder()],
    ['paymentToken', getAddressDecoder()],
    ['deadline', getI64Decoder()],
    ['status', getU8Decoder()],
    ['createdAt', getI64Decoder()],
    ['updatedAt', getI64Decoder()],
    ['deliverables', fixDecoderSize(getBytesDecoder(), 128)],
    ['bump', getU8Decoder()],
    ['reserved', fixDecoderSize(getBytesDecoder(), 31)],
  ]);
}

export function getWorkOrderAccountCodec(): Codec<WorkOrderAccountArgs, WorkOrderAccount> {
  return combineCodec(getWorkOrderAccountEncoder(), getWorkOrderAccountDecoder());
}

export function decodeWorkOrderAccount<TAddress extends string = string>(
  encodedAccount: EncodedAccount<TAddress>
): Account<WorkOrderAccount, TAddress>;
export function decodeWorkOrderAccount<TAddress extends string = string>(
  encodedAccount: MaybeEncodedAccount<TAddress>
): MaybeAccount<WorkOrderAccount, TAddress>;
export function decodeWorkOrderAccount<TAddress extends string = string>(
  encodedAccount: EncodedAccount<TAddress> | MaybeEncodedAccount<TAddress>
): Account<WorkOrderAccount, TAddress> | MaybeAccount<WorkOrderAccount, TAddress> {
  return decodeAccount(
    encodedAccount as MaybeEncodedAccount<TAddress>,
    getWorkOrderAccountDecoder()
  );
}

export async function fetchWorkOrderAccount<TAddress extends string = string>(
  rpc: Parameters<typeof fetchEncodedAccount>[0],
  address: Address<TAddress>,
  config?: FetchAccountConfig
): Promise<Account<WorkOrderAccount, TAddress>> {
  const maybeAccount = await fetchMaybeWorkOrderAccount(rpc, address, config);
  assertAccountExists(maybeAccount);
  return maybeAccount;
}

export async function fetchMaybeWorkOrderAccount<TAddress extends string = string>(
  rpc: Parameters<typeof fetchEncodedAccount>[0],
  address: Address<TAddress>,
  config?: FetchAccountConfig
): Promise<MaybeAccount<WorkOrderAccount, TAddress>> {
  const maybeAccount = await fetchEncodedAccount(rpc, address, config);
  return decodeWorkOrderAccount(maybeAccount);
}

export async function fetchAllWorkOrderAccount(
  rpc: Parameters<typeof fetchEncodedAccounts>[0],
  addresses: Array<Address>,
  config?: FetchAccountsConfig
): Promise<Account<WorkOrderAccount>[]> {
  const maybeAccounts = await fetchAllMaybeWorkOrderAccount(rpc, addresses, config);
  assertAccountsExist(maybeAccounts);
  return maybeAccounts;
}

export async function fetchAllMaybeWorkOrderAccount(
  rpc: Parameters<typeof fetchEncodedAccounts>[0],
  addresses: Array<Address>,
  config?: FetchAccountsConfig
): Promise<MaybeAccount<WorkOrderAccount>[]> {
  const maybeAccounts = await fetchEncodedAccounts(rpc, addresses, config);
  return maybeAccounts.map((maybeAccount) => decodeWorkOrderAccount(maybeAccount));
} 