import { mixin, Model, raw } from 'objection';
import TenantModel from 'models/TenantModel';
import CustomViewBaseModel from './CustomViewBaseModel';
import ModelSetting from './ModelSetting';
import ModelSearchable from './ModelSearchable';
import { ProjectTaskChargeType } from '@/services/Projects/Tasks/constants';
import { number } from 'mathjs';

export default class Task extends mixin(TenantModel, [
  ModelSetting,
  CustomViewBaseModel,
  ModelSearchable,
]) {
  type!: string;
  rate!: number;
  actualHours!: number;
  invoicedHours!: number;
  estimateHours!: number;

  /**
   * Table name
   */
  static get tableName() {
    return 'tasks';
  }

  /**
   * Timestamps columns.
   */
  get timestamps() {
    return ['created_at', 'updated_at'];
  }

  /**
   * Virtual attributes.
   */
  static get virtualAttributes() {
    return [
      'actualAmount',
      'invoicedAmount',
      'estimateAmount',
      'billableAmount',
      'billableHours',
    ];
  }

  /**
   * Retrieves the actual amount.
   */
  get actualAmount(): number {
    return this.rate * this.actualHours;
  }

  /**
   * Retrieves the invoiced amount.
   */
  get invoicedAmount(): number {
    return this.rate * this.invoicedHours;
  }

  /**
   * Retrieves the estimate amount.
   */
  get estimateAmount(): number {
    return this.rate * this.estimateHours;
  }

  /**
   * Retrieves the billable amount.
   */
  get billableAmount() {
    return this.actualAmount - this.invoicedAmount;
  }

  /**
   * Retrieves the billable hours.
   */
  get billableHours() {
    return this.actualHours - this.invoicedHours;
  }

  /**
   * Model modifiers.
   */
  static get modifiers() {
    return {
      /**
       * Sumation of total actual hours.
       * @param builder
       */
      sumTotalActualHours(builder) {
        builder.sum('actualHours as totalActualHours');
      },

      /**
       * Sumation total estimate hours.
       * @param builder
       */
      sumTotalEstimateHours(builder) {
        builder.sum('estimateHours as totalEstimateHours');
      },

      /**
       * Sumation of total invoiced hours.
       * @param builder
       */
      sumTotalInvoicedHours(builder) {
        builder.sum('invoicedHours as totalInvoicedHours');
      },

      /**
       * Sumation of total actual amount.
       * @param builder
       */
      sumTotalActualAmount(builder) {
        builder.groupBy('totalActualAmount');
        builder.select(raw('ACTUAL_HOURS * RATE').as('totalActualAmount'));
      },

      /**
       * Sumation of total invoiced amount.
       * @param builder
       */
      sumTotalInvoicedAmount(builder) {
        this.groupBy('totalInvoicedAmount');
        builder.select(raw('INVOICED_HOURS * RATE').as('totalInvoicedAmount'));
      },

      /**
       * Sumation of total estimate amount.
       * @param builder
       */
      sumTotalEstimateAmount(builder) {
        builder.groupBy('totalEstimateAmount');
        builder.select(raw('ESTIMATE_HOURS * RATE').as('totalEstimateAmount'));
      },
    };
  }

  /**
   * Relationship mapping.
   */
  static get relationMappings() {
    const Time = require('models/Time');
    const Project = require('models/Project');

    return {
      /**
       * Project may has many associated tasks.
       */
      times: {
        relation: Model.HasManyRelation,
        modelClass: Time.default,
        join: {
          from: 'tasks.id',
          to: 'times.taskId',
        },
      },

      /**
       * Project may has many associated times.
       */
      project: {
        relation: Model.BelongsToOneRelation,
        modelClass: Project.default,
        join: {
          from: 'tasks.projectId',
          to: 'projects.id',
        },
      },
    };
  }
}
