import { ColumnDecimalTransformer } from '@core/utils'
import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'
import { SoftDeleteEntity } from '../entity'
import { ItemUnit, MenuItem } from '../menu'
import { OrderItemState } from './enums'
import { Order } from './order.model'

/**
 * Represents a single item in an order
 */
@Entity()
export class OrderItem extends SoftDeleteEntity<OrderItem> {
	/**
	 *  Name of the menu item
	 */
	@Column({
		type: 'varchar',
		length: 60,
		nullable: false,
	})
	name: string

	/**
	 * Total quantity ordered
	 */
	@Column({
		type: 'decimal',
		nullable: false,
		transformer: new ColumnDecimalTransformer(),
	})
	quantity: number

	/**
	 * The unit that is used to measure amount of item
	 */
	@Column({
		type: 'enum',
		enum: ItemUnit,
		default: ItemUnit.pieces,
		nullable: false,
	})
	quantityUnit: ItemUnit

	/**
	 * Unit price of the menu item
	 */
	@Column({
		type: 'decimal',
		nullable: false,
		transformer: new ColumnDecimalTransformer(),
	})
	unitPrice: number

	/**
	 * The quantity that has been paid
	 * NOTE: Do this set this property, use {@link payQuantity()} method
	 */
	@Column({
		type: 'decimal',
		nullable: false,
		transformer: new ColumnDecimalTransformer(),
	})
	paidQuantity: number

	/**
	 * True if item has been fully paid
	 */
	@Column({
		type: 'boolean',
		nullable: false,
		default: false,
	})
	paid: boolean

	/**
	 * Current state of the item
	 */
	@Column({
		type: 'enum',
		enum: OrderItemState,
		default: OrderItemState.pending,
		nullable: false,
	})
	state: OrderItemState

	/**
	 * Optional course of the item
	 */
	@Column({
		type: 'integer',
		nullable: true,
	})
	course?: number

	/**
	 * The order to which this sale item belongs
	 */
	@ManyToOne(() => Order, (_order) => _order.items, { nullable: false })
	order: Order

	/**
	 * The menu item that was ordered
	 */
	@ManyToOne(() => MenuItem, { nullable: false })
	@JoinColumn()
	menuItem: MenuItem

	payQuantity(quantity: number): void {
		if (this.paidQuantity + quantity > this.quantity) {
			throw new Error('Paid quantity must not exceed total quantity')
		}

		this.paidQuantity += quantity

		if (this.paidQuantity === this.quantity) {
			this.paid = true
		}
	}
}
