/*
 * Copyright (C) 2023 StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
import {Injectable} from '@angular/core';
import {SCDish, SCISO8601Date, SCPlace, SCSearchQuery, SCThingType} from '@openstapps/core';
import {DataProvider} from '../../../../data.provider';
import {mapValues} from '@openstapps/collection-utils';
import {SettingsProvider} from '../../../../../settings/settings.provider';
import {addDays, startOfHour} from 'date-fns';

@Injectable({
  providedIn: 'root',
})
export class PlaceMensaService {
  constructor(
    private dataProvider: DataProvider,
    readonly settingsProvider: SettingsProvider,
  ) {}

  /**
   * Fetches all dishes for this building
   *
   * Splits dishes as such that each list contains all dishes that are available at that day.
   */
  async getAllDishes(place: SCPlace, days: number): Promise<Record<SCISO8601Date, SCDish[]>> {
    const priceGroup = await this.settingsProvider.getSetting('profile', 'group');

    const request = Object.fromEntries(
      Array.from({length: days}, (_, i) => {
        const date = addDays(startOfHour(Date.now()), i).toISOString();
        return [
          date,
          {
            filter: {
              arguments: {
                filters: [
                  {
                    arguments: {
                      field: 'offers.inPlace.uid',
                      value: place.uid,
                    },
                    type: 'value',
                  },
                  {
                    arguments: {
                      field: 'type',
                      value: SCThingType.Dish,
                    },
                    type: 'value',
                  },
                  {
                    arguments: {
                      field: 'offers.availabilityRange',
                      scope: 'd',
                      time: date,
                    },
                    type: 'availability',
                  },
                ],
                operation: 'and',
              },
              type: 'boolean',
            },
            sort: [
              {
                arguments: {
                  field: `offers.prices.${(priceGroup.value as string).replace(/s$/, '')}`,
                },
                order: 'desc',
                type: 'generic',
              },
            ],
            size: 1000,
          } satisfies SCSearchQuery,
        ];
      }),
    );

    return mapValues(await this.dataProvider.multiSearch(request), it => it.data) as Record<
      SCISO8601Date,
      SCDish[]
    >;
  }
}
