import { ClassError } from '@tomei/general';
import { IFeedAttr } from '../../interfaces/price-feed-attr.interface';
import { FeedRepository } from './feed.repository';
import { NonSourceFeedName, SourceFeedName } from '../../enum/feed.enum';
import { FeedManualPriceHistory } from '../feed-manual-price-history/feed-manual-price-history';
import { FeedHistory } from '../feed-history/feed-history';
import { TomeiPriceHistory } from '../tomei-price/tomei-price';

export class Feed implements IFeedAttr {
  FeedName: SourceFeedName | NonSourceFeedName;
  IsSourcePriceYN: string;
  IsManualPriceActivatedYN: string;
  CurrentManualPriceHistoryId: string;

  protected static _Repo = new FeedRepository();

  constructor(feedAttr?: IFeedAttr) {
    if (feedAttr) {
      this.FeedName = feedAttr.FeedName;
      this.IsSourcePriceYN = feedAttr.IsSourcePriceYN;
      this.IsManualPriceActivatedYN = feedAttr.IsManualPriceActivatedYN;
      this.CurrentManualPriceHistoryId = feedAttr.CurrentManualPriceHistoryId;
    }
  }

  public static async init(dbTransaction: any, FeedName?: string) {
    try {
      if (FeedName) {
        const feed = await Feed._Repo.findByPk(FeedName, dbTransaction);
        if (feed) {
          return new Feed(feed);
        } else {
          throw new ClassError('Feed', 'FeedErrMsg00', 'Feed Not Found');
        }
      }
      return new Feed();
    } catch (error) {
      throw new ClassError('Feed', 'FeedErrMsg01', error.message);
    }
  }

  public async save(dbTransaction: any) {
    try {
      const feed = await Feed._Repo.findOne({
        where: {
          FeedName: this.FeedName,
        },
        transaction: dbTransaction,
      });
      const payload: IFeedAttr = {
        FeedName: this.FeedName,
        IsSourcePriceYN: this.IsSourcePriceYN,
        IsManualPriceActivatedYN: this.IsManualPriceActivatedYN,
        CurrentManualPriceHistoryId: this.CurrentManualPriceHistoryId,
      };
      if (feed) {
        await Feed._Repo.update(payload, {
          where: {
            FeedName: this.FeedName,
          },
          transaction: dbTransaction,
        });
      } else {
        await Feed._Repo.create(payload, { transaction: dbTransaction });
      }
    } catch (error) {
      throw new ClassError('Feed', 'FeedErrMsg02', error.message);
    }
  }

  public async setManualPrice(
    activatedById: string,
    buyPrice: number,
    sellPrice: number,
    dbTransaction: any,
  ) {
    try {
      //Instantiate a new feed manual price history
      let feedManualPriceHistory = await FeedManualPriceHistory.init();
      feedManualPriceHistory.FeedName = this.FeedName;
      feedManualPriceHistory.ActivatedById = activatedById;
      //Call FeedManualPriceHistory.create to create a new manual price history record
      feedManualPriceHistory = await feedManualPriceHistory.create(
        this.FeedName,
        activatedById,
        buyPrice,
        sellPrice,
        dbTransaction,
      );
      //Update the manual price history id
      this.CurrentManualPriceHistoryId =
        feedManualPriceHistory.FeedManualPriceHistoryId;
      //Update the manual price status
      this.IsManualPriceActivatedYN = 'Y';
      //Update the feed record in the database
      await this.save(dbTransaction);
    } catch (error) {
      throw error;
    }
  }

  public async deactivateManualPrice(
    dbTransaction: any,
    deactivatedById: string,
  ) {
    try {
      //Call FeedManualPriceHistory.deactivate to deactivate the manual price
      await FeedManualPriceHistory.deactivate(
        this.FeedName,
        deactivatedById,
        dbTransaction,
      );
      //Update the manual price status
      this.IsManualPriceActivatedYN = 'N';
      //Update the feed record in the database
      await this.save(dbTransaction);
    } catch (error) {
      throw error;
    }
  }

  public async createTomeiPriceHistory(
    feedHistory: FeedHistory,
    dbTransaction: any,
  ) {
    try {
      const feedMap: Record<string, NonSourceFeedName[]> = {
        [SourceFeedName.XAUMYR]: [
          NonSourceFeedName.GOLD1000G,
          NonSourceFeedName.GOLD500G,
        ],
        [SourceFeedName.XAGMYR]: [
          NonSourceFeedName.SILVER1000G,
          NonSourceFeedName.SILVER10OZ,
        ],
        // Add or remove mappings as needed
      };

      const nonSourceFeeds = feedMap[this.FeedName];
      if (nonSourceFeeds && nonSourceFeeds.length > 0) {
        for (const nonSourceFeed of nonSourceFeeds) {
          const tomeiPriceHistory = await TomeiPriceHistory.init();
          await tomeiPriceHistory.saveTomeiPrice(
            nonSourceFeed,
            feedHistory,
            undefined,
            undefined,
            undefined,
            dbTransaction,
          );
        }
      }
    } catch (error) {
      throw error;
    }
  }
}
