import * as React from 'react';
import { ProfileDetail } from 'components/profile-detail/ProfileDetail';
import UsageQuery from 'graphql/queries/usage';
import { isEmpty, sortBy } from 'lodash';
import { makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import AutoRefill from 'store/models/AutoRefill';
import Profile from 'store/models/Profile';
import UsagePack from 'store/models/UsageInfo';
import UsageItem from 'store/models/UsageItem';
import { IAlert, IAutoRefill, IUsagePack, UsageType } from 'typings';
import { formatDate, formatPrice, profileColor } from 'utils/helpers';
import { WithTranslation, withTranslation } from 'utils/i18n';

interface IDetailProps extends WithTranslation {
  profile: Profile;
  packId: string;
  onSelect(pack: UsagePack): any;
  onCancel({ autoRefill, pack }: { autoRefill?: AutoRefill; pack?: UsagePack }): any;
  onChange(autoRefill: AutoRefill, type: 'payment' | 'date'): any;
}

interface IConfirmChangeState {
  message: string;
  status: string;
}

class Detail extends React.Component<IDetailProps, IConfirmChangeState> {
  invalid = '';

  forms: any = [];

  state: IConfirmChangeState = {
    message: '',
    status: '',
  };

  mapAlerts = (a: IAlert) => ({ label: a.description, value: a.message });

  mapUsageItems = (u: UsageItem) => ({ label: u.title, value: u.used });

  generateInfo = (
    profile: Profile,
    pack: UsagePack,
    alerts: Array<IAlert>,
    excessPack?: UsagePack,
    autoRefill?: IAutoRefill,
  ) => {
    const { t } = this.props;
    let info = alerts.map(this.mapAlerts);

    if (excessPack && !pack.isExcessUsage) {
      const excessAlerts = excessPack.alerts.map(this.mapAlerts);

      info = info.concat(excessAlerts);
    }

    if (excessPack) {
      const { excessCount, info: packInfo } = excessPack;

      info.push({
        label: t('detail.info.excessCost'),
        value: formatPrice(excessCount * packInfo.price),
      });
    }

    if (autoRefill) {
      if (autoRefill.nextRefill) {
        info.push({
          label: t('detail.info.nextRefill'),
          value: formatDate(autoRefill.nextRefill, 'dd.MM.yyyy'),
        });
      } else {
        info.push({ label: t('detail.info.nextRefill'), value: t('detail.info.beginningofMonth') });
      }
    }

    if (pack && pack.validTo) {
      const showValidTime =
        !isEmpty(pack.info) &&
        ((!autoRefill && pack.info.contentType === 'refill') ||
          (profile.rateplan.isPrepaid && pack.info.contentType !== 'rateplan'));

      if (showValidTime) {
        info.push({
          label: t('detail.info.expiryDate'),
          value: formatDate(pack.validTo, 'dd.MM.yyyy'),
        });
      }
    }

    return info;
  };

  paymentInfo = (autoRefill?: IAutoRefill) => {
    const { onChange, t } = this.props;

    if (autoRefill) {
      if (autoRefill.paymentMethod) {
        const { maskedCardNumber, expiryMonth, expiryYear } = autoRefill.paymentMethod;

        return {
          title: t('detail.paymentSection.paymentInfo'),
          label: maskedCardNumber,
          value: `${expiryMonth}/${expiryYear}`,
          button: () => onChange(autoRefill, 'payment'),
          buttonText: t('detail.paymentSection.paymentChange'),
        };
      }
    }

    return null;
  };

  refillDateInfo = (autoRefill?: IAutoRefill) => {
    const { onChange, t } = this.props;

    if (autoRefill && autoRefill.nextRefill) {
      return {
        button: () => onChange(autoRefill, 'date'),
        buttonText: t('detail.date.changeDate'),
      };
    }
    return null;
  };

  constructor(props: IDetailProps) {
    super(props);

    makeObservable(this, {
      invalid: observable,
    });
  }

  render() {
    const { packId, profile, onSelect, onCancel, t } = this.props;

    return (
      <UsageQuery variables={{ subscriptionId: profile.subscriptionId }}>
        {({ data, loading, error }) => {
          if (error || !data || !data.me || loading) {
            return null;
          }

          const {
            me: { profiles },
          } = data;

          if (!profiles[0]) return null;

          const { packs } = profiles[0];

          const { rateplan } = profile;
          const orderedPacks = sortBy(
            packs.map((p: IUsagePack) => new UsagePack(p)),
            ['order'],
          );
          const pack = orderedPacks[parseInt(packId, 10)];
          const color = profileColor(rateplan);

          if (!pack || isEmpty(pack)) return null;
          const { info, alerts, items } = pack;

          if (!info) return null;

          const {
            description,
            detailedDescription,
            title,
            price,
            dataInEurope,
            categoryTitle,
            id,
            canCancel,
            canModify,
            typeId,
          } = info;

          const isUrlausn = pack?.servicepackId === 'S2113';
          const urlausnDescription = t('detail.urlausn.description');
          const urlausnButtonText = t('detail.urlausn.button');
          const autoRefill = profile.findAutoRefillForPack(
            orderedPacks as UsagePack[],
            parseInt(packId, 10),
          );
          const allowModify = rateplan.isPrepaid
            ? canModify && !!autoRefill
            : canModify && profile.hasOfferingsByTypeId(typeId as string);
          const excessPack = packs.find(
            (p: IUsagePack) => p.servicepackId === id && p.isExcessUsage,
          );

          const usageInfo = items
            .filter((i: UsageItem) => i.type !== UsageType.VALID_TIME)
            .map((i: UsageItem) => this.mapUsageItems(i));

          const extraInfo = this.generateInfo(
            profile,
            pack as UsagePack,
            alerts as IAlert[],
            excessPack as UsagePack,
            autoRefill,
          );
          const paymentInfo = this.paymentInfo(autoRefill);
          const refillDateInfo = this.refillDateInfo(autoRefill);

          return (
            <ProfileDetail
              color={color}
              title={title}
              price={price}
              canModify={allowModify}
              dataInEurope={dataInEurope}
              categoryTitle={categoryTitle}
              description={[detailedDescription || description, isUrlausn && urlausnDescription]
                .filter(Boolean)
                .join('\n\n')}
              onChange={() => onSelect(pack as UsagePack)}
              buttonText={t('detail.button.changeButton')}
              extraInfoTitle={t('detail.infosHeading')}
              extraInfo={extraInfo}
              usageInfoTitle={t('detail.usageHeading')}
              usageInfo={usageInfo}
              paymentInfo={paymentInfo}
              changeDate={refillDateInfo}
              canCancel={canCancel || !!autoRefill}
              cancelButtonText={
                autoRefill
                  ? t('detail.button.cancelAutoRefill')
                  : isUrlausn
                  ? urlausnButtonText
                  : t('detail.button.cancelButton')
              }
              onCancel={() => onCancel({ autoRefill, pack })}
            />
          );
        }}
      </UsageQuery>
    );
  }
}

export default withTranslation('subscription')(observer(Detail));
