import {
  Controller,
  Get,
  Param,
  HttpService,
  UseInterceptors,
  CacheInterceptor,
  CacheTTL,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { map, flatMap, catchError } from 'rxjs/operators';

import { BuildingService } from './building.service';
import { AxiosResponse } from 'axios';
import { ConfigService } from '@nestjs/config';

@Controller('buildings')
@UseInterceptors(CacheInterceptor)
export class BuildingController {
  private readonly rentCafe: string = this.configService.get<string>(
    'RENTCAFE',
  );
  // rentCafe =
  // 'https://api.rentcafe.com/rentcafeapi.aspx?apitoken=ODU0Nzk%3d-InaOhyAR1SE%3d&requestType=';

  constructor(
    private readonly httpService: HttpService,
    private buildingService: BuildingService,
    private readonly configService: ConfigService,
  ) {}

  @CacheTTL(3600)
  @Get(':id')
  async getAvailableUnits(
    @Param('id') id: string,
  ): Promise<Observable<AxiosResponse>> {
    const promos = await this.buildingService.getPromotions(id);
    const url = `${this.rentCafe}apartmentavailability&VoyagerPropertyCode=${id}`;
    const units = this.httpService.get(url).pipe(
      map(response => {
        const unit = response.data.map(val => {
          const specials = this.buildingService.checkSpecials(val, promos, id);
          const unitData = { ...val, ...specials, promotion: { ...promos } };
          return unitData;
        });
        return unit;
      }),
    );
    return units;
  }

  @CacheTTL(3600)
  @Get(':id/availability-list')
  async getAvailableUnitsFormatter(
    @Param('id') id: string,
  ): Promise<Observable<AxiosResponse<any>>> {
    const url = `${this.rentCafe}apartmentavailability&VoyagerPropertyCode=${id}`;
    const promos = await this.buildingService.getPromotions(id);
    const units = this.httpService.get(url).pipe(
      map(response => {
        const t = response.data.map(val => {
          if (val.Error) return val;

          const max = Math.floor(val.MaximumRent);
          const min = Math.floor(val.MinimumRent);

          const baths = val.Baths.replace('.00', '');
          const specialsObj = this.buildingService.checkSpecials(
            val,
            promos,
            id,
          );

          const unit = {
            ApartmentId: val.ApartmentId,
            name: val.ApartmentName,
            ApplyOnlineURL: val.ApplyOnlineURL,
            baths: baths,
            beds: val.Beds,
            floorplanId: val.FloorplanId,
            floorplanName: val.FloorplanName,
            max: max,
            min: min,
            sqft: val.SQFT,
            VoyagerPropertyCode: val.VoyagerPropertyCode,
            ...specialsObj,
          };
          return unit;
        });
        return t;
      }),
    );
    return units;
  }

  @CacheTTL(3600)
  @Get(':id/address')
  getAddress(@Param('id') id: string): Observable<AxiosResponse> {
    const url = `${this.rentCafe}property&type=propertyCode&VoyagerPropertyCode=${id}`;
    const propertyData = this.httpService
      .get(url)
      .pipe(map(response => response.data));
    return propertyData;
  }

  @CacheTTL(3600)
  @Get(':id/amenities')
  getPropertyInfoByVoyager(@Param('id') id: string): Observable<AxiosResponse> {
    const url = `${this.rentCafe}property&type=amenities&VoyagerPropertyCode=${id}`;
    const propertyData = this.httpService.get(url).pipe(
      map(response =>
        response.data
          .filter(evt => evt.FeaturedAmenity === 'True')
          .map(val => {
            return {
              AmenityName: val.AmenityName,
              CustomAmenityName: val.CustomAmenityName,
              Category: val.Description1,
            };
          }),
      ),
    );
    return propertyData;
  }

  @CacheTTL(3600)
  @Get(':id/hours')
  getContactInfoById(@Param('id') id: string): Observable<AxiosResponse> {
    const url = `${this.rentCafe}property&type=officeHours&VoyagerPropertyCode=${id}`;

    const hours = this.httpService.get(url).pipe(
      map(response =>
        response.data
          .filter(evt => !evt.Error)
          .map(val => {
            return this.buildingService.getWorkingHours(val);
          }),
      ),
    );
    return hours;
  }

  @CacheTTL(3600)
  @Get(':id/floorplans')
  getFloorplan(@Param('id') id: string): Observable<AxiosResponse> {
    const url = `${this.rentCafe}floorplan&VoyagerPropertyCode=${id}`;
    const floorplans = this.httpService
      .get(url)
      .pipe(map(response => response.data));
    return floorplans;
  }

  @CacheTTL(3600)
  @Get(':id/floorplansImages')
  getFloorplanImages(@Param('id') id: string): Observable<AxiosResponse> {
    const url = `${this.rentCafe}floorplan&VoyagerPropertyCode=${id}`;
    const floorplans = this.httpService.get(url).pipe(
      map(response => {
        const r = response.data
          .filter(x => x.AvailableUnitsCount > 0)
          .map(evt => {
            return {
              PropertyId: evt.PropertyId,
              FloorplanId: evt.FloorplanId,
              FloorplanName: evt.FloorplanName,
              AvailableUnitsCount: evt.AvailableUnitsCount,
              img: evt.FloorplanImageURL?.split(','),
              matchVoyagers: id,
            };
          });
        return r;
      }),
    );
    return floorplans;
  }

  @CacheTTL(3600)
  @Get(':id/floorplansImages/:floorplanId')
  getFloorplanImagesByFloorplanId(
    @Param('id') id: string,
    @Param('floorplanId') floorPlanId: string,
  ) {
    const url = `${this.rentCafe}floorplan&VoyagerPropertyCode=${id}`;
    const floorplans = this.httpService.get(url).pipe(
      map(response => {
        const r = response.data
          .filter(x => x.FloorplanId === floorPlanId)
          .map(evt => {
            let floorPlanImages = {};
            floorPlanImages['img'] = evt.FloorplanImageURL.split(',');
            floorPlanImages['alt'] = evt.FloorplanImageAltText.split(',');
            return floorPlanImages;
          });
        return r;
      }),
    );
    return floorplans;
  }

  @CacheTTL(3600)
  @Get(':id/floorplans/:floorplanId')
  async getFloorplanById(
    @Param('id') id: string,
    @Param('floorplanId') floorplanId: string,
  ): Promise<Observable<AxiosResponse>> {
    const promos = await this.buildingService.getPromotions(id);
    const url = `${this.rentCafe}apartmentavailability&VoyagerPropertyCode=${id}&floorplanId=${floorplanId}`;
    const floorplan = this.httpService.get(url).pipe(
      map(response => {
        const floorplans = response.data.map(evt => {
          let floorplan = { ...evt, promotion: { ...promos } };
          const specials = this.buildingService.checkSpecials(evt, promos, id);

          floorplan = { ...floorplan, ...specials };

          return floorplan;
        });
        return floorplans;
      }),
    );
    return floorplan;
  }
}
