import { Injectable } from '@nestjs/common';
import { BaseIndexManager } from 'src/core/modules/domain/usecase/managers/base-index.manager';
import { SelectQueryBuilder } from 'typeorm';
import {
  Param,
  RelationParam,
} from 'src/core/modules/domain/entities/base-filter.entity';
import { ItemEntity } from 'src/modules/item-related/item/domain/entities/item.entity';
import { DAY, STATUS } from 'src/core/strings/constants/base.constants';

@Injectable()
export class IndexItemRateManager extends BaseIndexManager<ItemEntity> {
  async prepareData(): Promise<void> {
    return;
  }

  async beforeProcess(): Promise<void> {
    return;
  }

  async afterProcess(): Promise<void> {
    this.result.data?.map((item) => {
      const prices = [];
      for (
        let d = new Date(this.filterParam.start_date);
        d <= new Date(this.filterParam.end_date);
        d.setDate(d.getDate() + 1)
      ) {
        const day: string = DAY[d.getDay()];
        const rates = item['item_rates']
          ?.filter((rate) => {
            const days: string[] = rate.season_period.days ?? [];
            if (rate.season_period.priority == 2) {
              return (
                rate.season_period?.status == STATUS.ACTIVE &&
                d >= new Date(rate.season_period.start_date) &&
                d <= new Date(rate.season_period.end_date) &&
                days.includes(day)
              );
            } else {
              return (
                rate.season_period?.status == STATUS.ACTIVE &&
                d >= new Date(rate.season_period.start_date) &&
                d <= new Date(rate.season_period.end_date)
              );
            }
          })
          .sort((a, b) => a.season_period.priority - b.season_period.priority);

        prices.push({
          date: new Date(d),
          price: rates[0]?.price ?? item.base_price,
          season_type: rates[0]?.season_period?.season_type ?? null,
          holiday_name: rates[0]?.season_period?.holiday_name ?? null,
        });
      }

      delete item['item_rates'];
      Object.assign(item, {
        dates: prices,
      });
    });

    return;
  }

  get relations(): RelationParam {
    return {
      // relation only join (for query purpose)
      joinRelations: [],

      // relation join and select (relasi yang ingin ditampilkan),
      selectRelations: [
        'bundling_items',
        'tenant',
        'item_rates',
        'item_rates.season_period',
        'season_period.season_type',
        'time_group',
      ],

      // relation yang hanya ingin dihitung (akan return number)
      countRelations: [],
    };
  }

  get selects(): string[] {
    return [
      `${this.tableName}.id`,
      `${this.tableName}.item_type`,
      `${this.tableName}.status`,
      `${this.tableName}.created_at`,
      `${this.tableName}.name`,
      `${this.tableName}.base_price`,
      `${this.tableName}.breakdown_bundling`,
      `${this.tableName}.share_profit`,

      'tenant.id',
      'tenant.name',

      'bundling_items.id',
      'bundling_items.name',

      'item_rates.id',
      'item_rates.price',

      'season_period.id',
      'season_period.status',
      'season_period.holiday_name',
      'season_period.start_date',
      'season_period.end_date',
      'season_period.priority',
      'season_period.days',

      'season_type.id',
      'season_type.name',

      'time_group.id',
      'time_group.name',
    ];
  }

  get specificFilter(): Param[] {
    return [
      {
        cols: `${this.tableName}.name`,
        data: this.filterParam.names,
      },
      {
        cols: `${this.tableName}.item_type::text`,
        data: this.filterParam.item_types,
      },
      {
        cols: `${this.tableName}.limit_type::text`,
        data: this.filterParam.limit_types,
      },
      {
        cols: `item_category.name`,
        data: this.filterParam.item_categories,
      },
    ];
  }

  setQueryFilter(
    queryBuilder: SelectQueryBuilder<ItemEntity>,
  ): SelectQueryBuilder<ItemEntity> {
    if (this.filterParam.tenant_ids?.length) {
      queryBuilder.andWhere(`${this.tableName}.tenant_id In (:...tenantIds)`, {
        tenantIds: this.filterParam.tenant_ids,
      });
    }

    queryBuilder.andWhere(`${this.tableName}.status In (:...statuses)`, {
      statuses: [STATUS.ACTIVE],
    });
    return queryBuilder;
  }
}
