import {
  BaseEntity,
  Column,
  Entity,
  Index,
  JoinColumn,
  ManyToOne,
  OneToMany,
  OneToOne,
  PrimaryGeneratedColumn,
} from 'typeorm';
import { BooleanTransformer } from '../../../utils/transformers/BooleanTransformer';
import { AddressEntity } from '../../address/entities/address.entity';
import { CarEntity } from '../../car/entities/car.entity';
import { DiscountEntity } from '../../discount/entities/discount.entity';
import { PollEntity } from '../../poll/entities/poll.entity';
import { ServiceReminderEntity } from '../../service/entities/service-reminder.entity';
import { UserEntity } from '../../user/entities/user.entity';
import { OrderItemEntity } from './order-item.entity';
import { PaymentEntity } from '../../payment/entities/payment.entity';

export enum OrderStatus {
  pending = 1,
  accepted = 2,
  sent = 3,
  delivered = 4,
  canceled = 5,
}
export enum OrderPaymentStatus {
  pending = 1,
  paid = 2,
  failed = 3,
  returned = 4,
  cardToCard = 5,
  unsettledPaid = 6,
}
export enum OrderPaymentMethod {
  online = 'online',
  offline = 'offline',
}
export enum OrderShippingType {
  normal = 1, // پست معمولی
  fast = 2, // پست پیشتاز
  custom = 3, // پست سفارشی
  peyk = 4, // پیک موتوری
  post = 5, // پست بین شهری
  inPerson = 6, // دریافت حضوری در شرکت
}
export enum OrderPaymentGateway {
  meli = 1,
  zarinpal = 2,
  kimia = 3,
  bimehMelat = 4, // TODO:
  snapp_pay = 5,
}
export enum OrderClientType {
  site = 1,
  app = 2,
  panel = 3,
}
export enum ShippingName {
  alopeyk = 'alopeyk',
  mahex = 'mahex',
}

@Index('userId', ['userId'], {})
@Entity('orders')
export class OrderEntity extends BaseEntity {
  @PrimaryGeneratedColumn({ type: 'int', name: 'id' })
  id: number;

  @Column('varchar', { name: 'orderNumber', length: 255 })
  orderNumber: string;

  @Column('char', { name: 'orderGuid', length: 36 })
  orderGuid: string;

  @Column('char', { name: 'userId', length: 36 })
  userId: string;

  @Column('char', { name: 'sellerId', length: 36 })
  sellerId: string;

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

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

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

  @Column('int', {
    name: 'isDeleted',
    default: () => "'0'",
    transformer: new BooleanTransformer(),
  })
  isDeleted: boolean;

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

  @Column('varchar', {
    name: 'paymentMethodSystemName',
    nullable: true,
    length: 20,
  })
  paymentMethodSystemName: OrderPaymentMethod | null;

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

  @Column('int', { name: 'VAT', nullable: true, default: () => "'0'" })
  vat: number | null;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  @Column('int', { name: 'deductionsAmount', default: () => "'0'" })
  deductionsAmount: number;

  @Column('int', { name: 'usedWalletAmount', default: () => "'0'" })
  usedWalletAmount: number;

  @Column('int', { name: 'finalAmount', default: () => "'0'" })
  finalAmount: number;

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

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

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

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

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

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

  @Column('int', {
    name: 'clientType',
    default: () => "'1'",
  })
  clientType: OrderClientType;

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

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

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

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

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

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

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

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

  /**
   * Map Relation
   */
  relatedOrder: OrderEntity[];

  /**
   * Relations
   */
  @OneToOne(() => DiscountEntity, (discount) => discount.order, {
    onDelete: 'NO ACTION',
    onUpdate: 'CASCADE',
  })
  @JoinColumn([{ name: 'couponCode', referencedColumnName: 'couponCode' }])
  coupon: DiscountEntity;

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

  @ManyToOne(() => UserEntity, (users) => users.orders, {
    onDelete: 'NO ACTION',
    onUpdate: 'CASCADE',
  })
  @JoinColumn([{ name: 'userId', referencedColumnName: 'id' }])
  user: UserEntity;

  @ManyToOne(() => UserEntity, (users) => users.serviceMans, {
    onDelete: 'NO ACTION',
    onUpdate: 'CASCADE',
  })
  @JoinColumn([{ name: 'serviceManId', referencedColumnName: 'id' }])
  serviceMan: UserEntity;

  @OneToMany(() => PaymentEntity, (payments) => payments.order)
  payments: PaymentEntity[];

  @OneToMany(
    () => ServiceReminderEntity,
    (serviceReminders) => serviceReminders.prevOrder,
  )
  serviceReminders: ServiceReminderEntity[];

  @ManyToOne(() => CarEntity, (cars) => cars.orders, {
    onDelete: 'NO ACTION',
    onUpdate: 'CASCADE',
  })
  @JoinColumn([{ name: 'carId', referencedColumnName: 'id' }])
  car: CarEntity;

  @OneToMany(() => PollEntity, (polls) => polls.order)
  polls: PollEntity[];

  @ManyToOne(() => AddressEntity, (addresses) => addresses.orders, {
    onDelete: 'NO ACTION',
    onUpdate: 'CASCADE',
  })
  @JoinColumn([{ name: 'addressId', referencedColumnName: 'id' }])
  address: AddressEntity;

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