import { Injectable } from '@angular/core';
import { assign, cloneDeep } from 'lodash-es';
import { FuseMockApiService, FuseMockApiUtils } from '@fuse/lib/mock-api';
import { statistics as statisticsData } from './data';
import { casinoStatistics as casinoStatisticsData } from './data';
import { slotStatistics as slotStatisticsData } from './data';
import { powerballStatistics as powerballStatisticsData } from './data';

@Injectable({
  providedIn: 'root',
})
export class ReportStatisticsMockApi {
  private _statistics: any[] = statisticsData;
  private _casinoStatistics: any[] = casinoStatisticsData;
  private _slotStatistics: any[] = slotStatisticsData;
  private _powerballStatistics: any[] = powerballStatisticsData;

  /**
   * Constructor
   */
  constructor(private _fuseMockApiService: FuseMockApiService) {
    // Register Mock API handlers
    this.registerHandlers();
  }

  // -----------------------------------------------------------------------------------------------------
  // @ Public methods
  // -----------------------------------------------------------------------------------------------------

  /**
   * Register Mock API handlers
   */
  registerHandlers(): void {
    // -----------------------------------------------------------------------------------------------------
    // @ Statistics - GET
    // -----------------------------------------------------------------------------------------------------
    this._fuseMockApiService
      .onGet('api/apps/report/statistics', 300)
      .reply(({ request }) => {
        // Get available queries
        const search = request.params.get('search');
        const sort = request.params.get('sort') || 'casinoUse';
        const order = request.params.get('order') || 'asc';
        const page = parseInt(request.params.get('page') ?? '1', 10);
        const size = parseInt(request.params.get('size') ?? '10', 10);

        // Clone the statistics
        let statistics: any[] | null = cloneDeep(this._statistics);

        // Sort the statistics
        if (
          sort === 'casinoUse' ||
          sort === 'slotUse' ||
          sort === 'powerballUse'
        ) {
          statistics.sort((a, b) => {
            const fieldA = a[sort].toString().toUpperCase();
            const fieldB = b[sort].toString().toUpperCase();
            return order === 'asc'
              ? fieldA.localeCompare(fieldB)
              : fieldB.localeCompare(fieldA);
          });
        } else {
          statistics.sort((a, b) =>
            order === 'asc' ? a[sort] - b[sort] : b[sort] - a[sort]
          );
        }

        // If search exists...
        if (search) {
          // Filter the statistics
          statistics = statistics.filter(
            (contact: any) =>
              contact.name &&
              contact.name.toLowerCase().includes(search.toLowerCase())
          );
        }

        // Paginate - Start
        const statisticsLength = statistics.length;

        // Calculate pagination details
        const begin = page * size;
        const end = Math.min(size * (page + 1), statisticsLength);
        const lastPage = Math.max(Math.ceil(statisticsLength / size), 1);

        // Prepare the pagination object
        let pagination = {};

        // If the requested page number is bigger than
        // the last possible page number, return null for
        // statistics but also send the last possible page so
        // the app can navigate to there
        if (page > lastPage) {
          statistics = null;
          pagination = {
            lastPage,
          };
        } else {
          // Paginate the results by size
          statistics = statistics.slice(begin, end);

          // Prepare the pagination mock-api
          pagination = {
            length: statisticsLength,
            size: size,
            page: page,
            lastPage: lastPage,
            startIndex: begin,
            endIndex: end - 1,
          };
        }

        // Return the response
        return [
          200,
          {
            statistics,
            pagination,
          },
        ];
      });

    // -----------------------------------------------------------------------------------------------------
    // @ Statistics - GET
    // -----------------------------------------------------------------------------------------------------
    this._fuseMockApiService
      .onGet('api/apps/report/statistics/statistics')
      .reply(({ request }) => {
        // Get the id from the params
        const id = request.params.get('id');

        // Clone the statistics
        const statistics = cloneDeep(this._statistics);

        // Find the statistics
        statistics.find((item: any) => item.id === id);

        // Return the response
        return [200, statistics];
      });

    // -----------------------------------------------------------------------------------------------------
    // @ CasinoStatistics - GET
    // -----------------------------------------------------------------------------------------------------
    this._fuseMockApiService
      .onGet('api/apps/report/statistics/casino-statistics')
      .reply(({ request }) => {
        // Get the type from the params
        const id = request.params.get('type');

        // Clone the statistics
        const casinoStatistics = cloneDeep(this._statistics);

        // Find the statistics
        casinoStatistics.find((item: any) => item.type === id);

        // Return the response
        return [200, casinoStatistics];
      });

    // -----------------------------------------------------------------------------------------------------
    // @ SlotStatistics - GET
    // -----------------------------------------------------------------------------------------------------
    this._fuseMockApiService
      .onGet('api/apps/report/statistics/slot-statistics')
      .reply(({ request }) => {
        // Get the type from the params
        const id = request.params.get('type');

        // Clone the statistics
        const slotStatistics = cloneDeep(this._statistics);

        // Find the statistics
        slotStatistics.find((item: any) => item.type === id);

        // Return the response
        return [200, slotStatistics];
      });

    // -----------------------------------------------------------------------------------------------------
    // @ PowerballStatistics - GET
    // -----------------------------------------------------------------------------------------------------
    this._fuseMockApiService
      .onGet('api/apps/report/statistics/powerball-statistics')
      .reply(({ request }) => {
        // Get the type from the params
        const id = request.params.get('type');

        // Clone the statistics
        const powerballStatistics = cloneDeep(this._statistics);

        // Find the statistics
        powerballStatistics.find((item: any) => item.type === id);

        // Return the response
        return [200, powerballStatistics];
      });

    // -----------------------------------------------------------------------------------------------------
    // @ Statistics - POST
    // -----------------------------------------------------------------------------------------------------
    this._fuseMockApiService
      .onPost('api/apps/report/statistics/statistics')
      .reply(() => {
        // Generate a new statistics
        const newStatistics = {
          id: FuseMockApiUtils.guid(),
          category: '',
          name: 'A New User',
          description: '',
          tags: [],
          sku: '',
          barcode: '',
          brand: '',
          vendor: '',
          stock: '',
          reserved: '',
          cost: '',
          basePrice: '',
          taxPercent: '',
          price: '',
          weight: '',
          thumbnail: '',
          images: [],
          active: false,
        };

        // Unshift the new statistics
        this._statistics.unshift(newStatistics);

        // Return the response
        return [200, newStatistics];
      });

    // -----------------------------------------------------------------------------------------------------
    // @ Statistics - PATCH
    // -----------------------------------------------------------------------------------------------------
    this._fuseMockApiService
      .onPatch('api/apps/report/statistics/statistics')
      .reply(({ request }) => {
        // Get the id and statistics
        const id = request.body.id;
        const statistics = cloneDeep(request.body.statistics);

        // Prepare the updated statistics
        let updatedStatistics = null;

        // Find the statistics and update it
        this._statistics.forEach((item, index, statistics) => {
          if (item.id === id) {
            // Update the statistics
            statistics[index] = assign({}, statistics[index], statistics);

            // Store the updated Statistics
            updatedStatistics = statistics[index];
          }
        });

        // Return the response
        return [200, updatedStatistics];
      });

    // -----------------------------------------------------------------------------------------------------
    // @ Statistics - DELETE
    // -----------------------------------------------------------------------------------------------------
    this._fuseMockApiService
      .onDelete('api/apps/report/statistics/statistics')
      .reply(({ request }) => {
        // Get the id
        const id = request.params.get('id');

        // Find the statistics and delete it
        this._statistics.forEach((item, index) => {
          if (item.id === id) {
            this._statistics.splice(index, 1);
          }
        });

        // Return the response
        return [200, true];
      });
  }
}
