import { Inject, LOCALE_ID, Pipe, PipeTransform } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { DatePipe as BaseDatePipe } from '@angular/common';
import { getLeftDateTime } from '@iqser/common-ui/lib/utils';
import dayjs from 'dayjs';

@Pipe({
    name: 'date',
})
export class DatePipe extends BaseDatePipe implements PipeTransform {
    constructor(@Inject(LOCALE_ID) private readonly _locale: string, private readonly _translateService: TranslateService) {
        super(_locale);
    }

    transform(value: null | undefined, format?: string, timezone?: string, locale?: string): null;
    transform(value: Date | string | number, format?: string, timezone?: string, locale?: string): string;
    transform(value: Date | string | number | null | undefined, format?: string, timezone?: string, locale?: string): string | null {
        if (typeof value === 'string') {
            if (format === 'timeFromNow') {
                return this._getTimeFromNow(value);
            }
            if (format === 'sophisticatedDate') {
                return this._getSophisticatedDate(value);
            }
            if (format === 'exactDate') {
                return this._getExactDate(value);
            }
        }
        try {
            return super.transform(value, format, timezone, locale || this._translateService.currentLang);
        } catch (e) {
            return '-';
        }
    }

    private _getTimeFromNow(value: string) {
        const { daysLeft, hoursLeft, minutesLeft } = getLeftDateTime(value);

        if (daysLeft === 0 && hoursLeft === 0 && minutesLeft > 0) {
            return this._translateService.instant('time.less-than-an-hour');
        }

        const hoursDisplay: string = this._translateService.instant('time.hours', { hours: hoursLeft });

        if (daysLeft === 0 && hoursLeft > 0) {
            return hoursDisplay;
        }

        const daysDisplay: string = this._translateService.instant('time.days', { days: daysLeft });

        if (daysLeft > 0 && hoursLeft > 0) {
            return `${daysDisplay} ${hoursDisplay}`;
        }
        if (daysLeft > 0) {
            return daysDisplay;
        }

        return this._translateService.instant('time.no-time-left');
    }

    private _getSophisticatedDate(item: string) {
        const date = dayjs(item);
        const day = date.date();
        const month = date.month();
        const year = date.year();

        const now = dayjs(Date.now());
        const yesterday = now.clone().subtract(1, 'days').startOf('day');
        const thisDay = now.date();
        const thisMonth = now.month();
        const thisYear = now.year();

        const isTodayFormat = date.isSame(new Date(), 'day');
        if (isTodayFormat) {
            return dayjs(date, ['h:mm A']).format('hh:mm A');
        }

        const isYesterdayFormat = date.isSame(yesterday, 'day');
        if (isYesterdayFormat) {
            return this._translateService.instant('yesterday');
        }

        const isShortMonthFormat =
            year === thisYear &&
            ((month === thisMonth && day !== thisDay && day !== thisDay - 1) || (month !== thisMonth && month >= thisMonth - 2));
        if (isShortMonthFormat) {
            const translatedMonth = dayjs.monthsShort()[month];
            return `${day} ${translatedMonth}`;
        }

        const isShortMonthYearFormat = (year === thisYear && month <= thisMonth - 3) || year === thisYear - 1;
        if (isShortMonthYearFormat) {
            const translatedMonth = dayjs.monthsShort()[month];
            return `${translatedMonth} ${year}`;
        }

        return year;
    }

    private _getExactDate(item: string) {
        const date = dayjs(item);
        const day = date.date();
        const month = dayjs.monthsShort()[date.month()];
        const year = date.year();
        const hour = date.hour().toString(10).padStart(2, '0');
        const minute = date.minute().toString(10).padStart(2, '0');

        return this._translateService.instant('exact-date', {
            day,
            month,
            year,
            hour,
            minute,
        });
    }
}
