import { Query } from '../common/query'
import { IdParam, PagingQuery } from '../common/types'

// Models for NFTs
export interface Nft {
	id: number
	name: string
	description?: string
	externalUrl?: string
	image?: string
	imageData?: string
	backgroundColor?: string
	animationUrl?: string
	youtubeUrl?: string
	thumbnail?: string
	owner?: string
	frozen?: boolean
	collectionId?: number
	status?: NftStatus
	faceValue?: number
	apiUserId?: number
	organizerId?: string
	currency?: string
	createdAt?: Date
	updatedAt?: Date
	attribute?: NftRelations[]
	sale?: NftSale
}

export interface NftAttribute {
	id: number
	value: string
	traitType: string
	displayType?: string
}

export interface NftSale {
	saleStartsAt: string
	saleEndsAt?: string
}

export interface NftCollection {
	id: number
	name: string
	description: string
	imageUrl?: string
	organizerId?: string
	apiUserId: number
	createdAt?: Date
	updatedAt?: Date
	nft?: Nft[]
}

// Utility types
export interface NftCollectionRelations extends Query {
	nft?: boolean | NftRelations
}

export interface NftRelations extends Query {
	attribute?: boolean
	collection?: boolean | NftCollectionRelations
	sale?: boolean
}

export interface NftQuery extends PagingQuery {
	owner?: string
	collection_ids?: number[]
	attribute_trait_type?: string // Used with attribute_value to filter out all NFTs with the given trait type and value
	attribute_value?: string
	api_user_name?: string
	status?: NftStatus
	organizer_id?: string
	with?: NftRelations
	sort_by?: string
}

export enum NftStatus {
	Available = 'available',
	Reserved = 'reserved',
	Confirmed = 'confirmed',
	Committed = 'committed',
	Issued = 'issued',
}

export interface SingleNftQuery extends IdParam {
	with?: NftRelations
}

export interface NftCollectionQuery extends PagingQuery {
	with?: NftCollectionRelations
	sort_by?: string
	organizer_id?: string
}

export interface SingleNftCollectionQuery extends IdParam {
	with?: NftCollectionRelations
}

export type NftAttributeCreate = Omit<NftAttribute, 'id'>
export type NftCreate = Omit<Nft, 'id' | 'attribute' | 'apiUserId'> & {
	attribute?: NftAttributeCreate[]
}

export type NftUpdate = Partial<Omit<Nft, 'organizerId' | 'apiUserId'>>

export type NftCollectionCreate = Omit<NftCollection, 'id' | 'apiUserId'>

export type NftCollectionUpdate = Partial<
	Omit<NftCollection, 'organizerId' | 'apiUserId'>
>

export enum ProviderKey {
	Stripe = 'stripe',
	OpenPayment = 'open-payment',
}

export interface NftOrderCreate {
	nftIds: number[]
	ownerId: string
	chaincodeId: string
	paymentProvider?: ProviderKey
	paymentMetadata?: {
		redirectUrl?: string
		billing?: {
			street1: string
			city: string
			state: string
			postcode: string
			country: string
		}
		customer?: {
			givenName: string
			email: string
			surname: string
		}
	}
}

export interface NftOrder {
	id: number
	ownerId: string
	paymentId: string
	paymentProvider: string
	status: NftOrderStatus
	total: number
	currency: string
	createdAt: string
	updatedAt: string
	nft?: Nft[]
}

export interface NewNftOrder extends NftOrder {
	payment: NftPayment
}

export interface NftPayment {
	id: string
	client_secret: string
	publishable_key: string
	metadata: Record<string, unknown>
}

export interface NftOrderRelations extends Query {
	nft: boolean | NftRelations
}

export interface OrderQuery extends PagingQuery {
	with?: NftOrderRelations
	sort_by?: string
}

export interface NftBatchCreate {
	collectionId: number
	quantity: number
	nft: NftCreate
}

export interface NftMint {
	nftId: number
	chaincodeId: string
	account: string
}

export enum NftOrderStatus {
	PaymentProcessing = 'PAYMENT_PROCESSING',
	Canceled = 'CANCELED',
	Completed = 'COMPLETED',
}
