import { VirtualColumn } from 'src/utils/decorators/virtual-column.decorator';
import { NumberTransformer } from 'src/utils/transformers/NumberTransformer';
import {
  BaseEntity,
  Column,
  Entity,
  Generated,
  Index,
  JoinColumn,
  ManyToOne,
  OneToMany,
} from 'typeorm';
import { BooleanTransformer } from '../../../utils/transformers/BooleanTransformer';
import { CategoryEntity } from '../../category/entities/category.entity';
import { ColorEntity } from '../../color/entities/color.entity';
import { LogEntity } from '../../log/entities/log.entity';
import { ManufacturerEntity } from '../../manufacturer/entities/manufacturer.entity';
import { OrderItemEntity } from '../../order/entities/order-item.entity';
import { ProductAttributeMappingEntity } from './product-attribute-mapping.entity';
import { ProductMakerBrandMappingEntity } from './product-maker-brand-mapping.entity';
import { ProductNotifQuantityEntity } from './product-notif-quantity.entity';
import { ProductPictureMappingEntity } from './product-picture-mapping.entity';
import { QuantityUnitEntity } from './quantity-unit.entity';
import { UserEntity } from '../../user/entities/user.entity';

export enum ProductWaitingOperation {
  add = 'add',
  update = 'update',
  delete = 'delete',
  publish = 'publish',
  un_publish = 'un_publish',
}

@Index('categoryId', ['categoryId'], {})
@Index('manufacturerId', ['manufacturerId'], {})
@Index('quantityUnitId', ['quantityUnitId'], {})
@Index('taxCategoryId', ['taxCategoryId'], {})
@Index('fk_products_users1_idx', ['creatorUserId'], {})
@Entity('products')
export class ProductEntity extends BaseEntity {
  @Generated('uuid')
  @Column('char', { primary: true, name: 'id', length: 36 })
  id: string;

  @Column('int', { name: 'productId' })
  productId: number;

  @Column('char', { name: 'creatorUserId', nullable: true, length: 36 })
  creatorUserId: string | null;

  @Column('enum', {
    name: 'isWaitingOperation',
    enum: ProductWaitingOperation,
    nullable: true,
  })
  isWaitingOperation: ProductWaitingOperation | null;

  @Column('varchar', { name: 'name', nullable: true, length: 100 })
  name: string | null;

  @Column('varchar', { name: 'shortDescription', nullable: true, length: 255 })
  shortDescription: string | null;

  @Column('text', { name: 'fullDescription', nullable: true })
  fullDescription: string | null;

  @Column('varchar', { name: 'adminComment', nullable: true, length: 255 })
  adminComment: string | null;

  @Column('tinyint', {
    name: 'showOnHomePage',
    nullable: true,
    width: 1,
    transformer: new BooleanTransformer(),
  })
  showOnHomePage: boolean | null;

  @Column('int', { name: 'homePageDisplayOrder', nullable: true })
  homePageDisplayOrder: number | null;

  @Column('varchar', { name: 'metaKeywords', nullable: true, length: 255 })
  metaKeywords: string | null;

  @Column('varchar', { name: 'metaDescription', nullable: true, length: 255 })
  metaDescription: string | null;

  @Column('varchar', { name: 'metaTitle', nullable: true, length: 255 })
  metaTitle: string | null;

  @Column('varchar', {
    name: 'manufacturerPartNumber',
    nullable: true,
    length: 255,
  })
  manufacturerPartNumber: string | null;

  @Column('tinyint', {
    name: 'isFreeShipping',
    nullable: true,
    width: 1,
    transformer: new BooleanTransformer(),
  })
  isFreeShipping: boolean | null;

  @Column('tinyint', {
    name: 'isTaxExempt',
    nullable: true,
    width: 1,
    transformer: new BooleanTransformer(),
  })
  isTaxExempt: boolean | null;

  @Column('int', { name: 'taxCategoryId', nullable: true })
  taxCategoryId: number | null;

  @Column('int', { name: 'stockQuantity', nullable: true })
  stockQuantity: number | null;

  @Column('int', { name: 'governmentOilStockQuantity', nullable: true })
  governmentOilStockQuantity: number | null;

  @Column('int', { name: 'minStockQuantity', nullable: true })
  minStockQuantity: number | null;

  @Column('int', { name: 'notifyAdminForQuantityBelow', nullable: true })
  notifyAdminForQuantityBelow: number | null;

  @Column('int', { name: 'orderMinimumQuantity', nullable: true })
  orderMinimumQuantity: number | null;

  @Column('int', { name: 'orderMaximumQuantity', nullable: true })
  orderMaximumQuantity: number | null;

  @Column('tinyint', {
    name: 'disableBuyButton',
    nullable: true,
    width: 1,
    transformer: new BooleanTransformer(),
  })
  disableBuyButton: boolean | null;

  @Column('tinyint', {
    name: 'disableWishlistButton',
    nullable: true,
    width: 1,
    transformer: new BooleanTransformer(),
  })
  disableWishlistButton: boolean | null;

  @Column('tinyint', {
    name: 'callForPrice',
    nullable: true,
    width: 1,
    transformer: new BooleanTransformer(),
  })
  callForPrice: boolean | null;

  @Column('int', { name: 'price', nullable: true })
  price: number | null;

  @Column('int', { name: 'priceInService', nullable: true })
  priceInService: number | null;

  @Column('int', { name: 'oldPrice', nullable: true })
  oldPrice: number | null;

  @Column('int', { name: 'mainPrice', nullable: true })
  mainPrice: number | null;

  @Column('int', { name: 'specialPrice', nullable: true })
  specialPrice: number | null;

  @Column('int', { name: 'governmentPrice', nullable: true })
  governmentPrice: number | null;

  @Column('datetime', { name: 'specialPriceStartDateTime', nullable: true })
  specialPriceStartDateTime: Date | null;

  @Column('datetime', { name: 'specialPriceEndDateTime', nullable: true })
  specialPriceEndDateTime: Date | null;

  @Column('tinyint', {
    name: 'isGiftCard',
    nullable: true,
    width: 1,
    transformer: new BooleanTransformer(),
  })
  isGiftCard: boolean | null;

  @Column('decimal', {
    name: 'weight',
    nullable: true,
    precision: 10,
    scale: 2,
  })
  weight: string | null;

  @Column('decimal', {
    name: 'length',
    nullable: true,
    precision: 10,
    scale: 2,
  })
  length: string | null;

  @Column('decimal', { name: 'width', nullable: true, precision: 10, scale: 2 })
  width: string | null;

  @Column('decimal', {
    name: 'height',
    nullable: true,
    precision: 10,
    scale: 2,
  })
  height: string | null;

  @Column('int', { name: 'quantityUnitId', nullable: true })
  quantityUnitId: number | null;

  @Column('varchar', {
    name: 'image',
    length: 255,
    default: () => "'/images/no-photo.jpg'",
  })
  image: string;

  @Column('int', { name: 'displayOrder', nullable: true })
  displayOrder: number | null;

  @Column('tinyint', {
    name: 'published',
    nullable: true,
    width: 1,
    transformer: new BooleanTransformer(),
  })
  published: boolean | null;

  @Column('tinyint', {
    name: 'deleted',
    nullable: true,
    width: 1,
    default: () => "'0'",
    transformer: new BooleanTransformer(),
  })
  deleted: boolean | null;

  @Column('tinyint', {
    name: 'onlyOrderInService',
    nullable: false,
    width: 1,
    default: () => "'0'",
    transformer: new BooleanTransformer(),
  })
  onlyOrderInService: boolean;

  @Column('int', { name: 'manufacturerId', nullable: true })
  manufacturerId: number | null;

  @Column('int', { name: 'categoryId', nullable: true })
  categoryId: number | null;

  @Column('tinyint', {
    name: 'isShowOldPrice',
    nullable: true,
    width: 1,
    transformer: new BooleanTransformer(),
  })
  isShowOldPrice: boolean | null;

  @Column('datetime', { name: 'createdAt' })
  createdAt: Date;

  @Column('datetime', { name: 'updatedAt' })
  updatedAt: Date;

  /**
   * Relations
   */
  @OneToMany(
    () => ProductMakerBrandMappingEntity,
    (makerBrandMappings) => makerBrandMappings.product,
  )
  makerBrandMappings: ProductMakerBrandMappingEntity[];

  @ManyToOne(() => CategoryEntity, (categories) => categories.products, {
    onDelete: 'SET NULL',
    onUpdate: 'CASCADE',
  })
  @JoinColumn([{ name: 'categoryId', referencedColumnName: 'id' }])
  category: CategoryEntity;

  @OneToMany(() => ColorEntity, (colors) => colors.product)
  colors: ColorEntity[];

  // @OneToMany(
  //   () => DiscountProductMappings,
  //   (discountProductMappings) => discountProductMappings.product,
  // )
  // discountProductMappings: DiscountProductMappings[];

  @OneToMany(() => OrderItemEntity, (orderItems) => orderItems.product)
  orderItems: OrderItemEntity[];

  // @OneToMany(
  //   () => PackageProductMappings,
  //   (packageProductMappings) => packageProductMappings.product,
  // )
  // packageProductMappings: PackageProductMappings[];

  @OneToMany(
    () => ProductPictureMappingEntity,
    (pictureMappings) => pictureMappings.product,
  )
  pictureMappings: ProductPictureMappingEntity[];

  @OneToMany(
    () => ProductAttributeMappingEntity,
    (productAtionattributeOptionMappings) =>
      productAtionattributeOptionMappings.product,
  )
  attributeMappings: ProductAttributeMappingEntity[];

  // @OneToMany(
  //   () => ProductTagMappings,
  //   (productTagMappings) => productTagMappings.product,
  // )
  // productTagMappings: ProductTagMappings[];

  // @ManyToOne(() => Taxcategories, (taxcategories) => taxcategories.products, {
  //   onDelete: 'NO ACTION',
  //   onUpdate: 'CASCADE',
  // })
  // @JoinColumn([{ name: 'taxCategoryId', referencedColumnName: 'id' }])
  // taxCategory: Taxcategories;

  @ManyToOne(
    () => QuantityUnitEntity,
    (quantityunits) => quantityunits.products,
    {
      onDelete: 'NO ACTION',
      onUpdate: 'CASCADE',
    },
  )
  @JoinColumn([{ name: 'quantityUnitId', referencedColumnName: 'id' }])
  quantityUnit: QuantityUnitEntity;

  @ManyToOne(
    () => ManufacturerEntity,
    (manufacturers) => manufacturers.products,
    {
      onDelete: 'SET NULL',
      onUpdate: 'CASCADE',
    },
  )
  @JoinColumn([{ name: 'manufacturerId', referencedColumnName: 'id' }])
  manufacturer: ManufacturerEntity;

  @OneToMany(
    () => ProductNotifQuantityEntity,
    (productNotifQuantities) => productNotifQuantities.product,
  )
  productNotifQuantities: ProductNotifQuantityEntity[];

  @OneToMany(() => LogEntity, (logs) => logs.affectedProduct)
  logs: LogEntity[];

  /**
   * Virtual columns
   */
  @VirtualColumn('countNotifQuantity', {
    transformer: new NumberTransformer(),
  })
  countNotifQuantity: number;

  @ManyToOne(() => UserEntity, (users) => users.products, {
    onDelete: 'NO ACTION',
    onUpdate: 'NO ACTION',
  })
  @JoinColumn([{ name: 'creatorUserId', referencedColumnName: 'id' }])
  creatorUser: UserEntity;
}
