import {
  IsInt,
  IsPositive
} from "class-validator";
import { BeforeInsert, BeforeUpdate, Column, Entity, Index, ManyToOne, PrimaryGeneratedColumn, TableInheritance } from "typeorm";
import { ResponseDonation } from '../responses/ResponseDonation';
import type { Donor } from './Donor';

/**
 * Defines the Donation entity.
 * A donation just associates a donor with a donation amount.
 * The specifics of the amoun's determination has to be implemented in child classes.
 */
@Entity()
@TableInheritance({ column: { name: "type", type: "varchar" } })
@Index(['donor'])
export abstract class Donation {
  /**
   * Autogenerated unique id (primary key).
   */
  @PrimaryGeneratedColumn()
  @IsInt()
  id: number;

  /**
   * The donations's donor.
   */
  @ManyToOne(() => require("./Donor").Donor, (donor: Donor) => donor.donations)
  donor!: Donor;

  /**
   * The donation's amount in cents (or whatever your currency's smallest unit is.).
   * The exact implementation may differ for each type of donation.
   */
  public abstract get amount(): number;

  /**
   * The donation's paid amount in cents (or whatever your currency's smallest unit is.).
   * Used to mark donations as paid.
   */
  @Column({ nullable: true })
  @IsInt()
  paidAmount: number;

  @Column({ type: 'bigint', nullable: true, readonly: true })
  @IsInt()
  @IsPositive()
  created_at: number;

  @Column({ type: 'bigint', nullable: true })
  @IsInt()
  @IsPositive()
  updated_at: number;

  @BeforeInsert()
  public setCreatedAt() {
    this.created_at = Math.floor(Date.now() / 1000);
    this.updated_at = Math.floor(Date.now() / 1000);
  }

  @BeforeUpdate()
  public setUpdatedAt() {
    this.updated_at = Math.floor(Date.now() / 1000);
  }

  /**
   * Turns this entity into it's response class.
   */
  public toResponse(): ResponseDonation {
    return new ResponseDonation(this);
  }
}