import Component from '@glimmer/component';
import moment from 'moment-timezone';
import {action} from '@ember/object';
import {getNonDecimal, getSymbol} from 'ghost-admin/utils/currency';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency';
import {tracked} from '@glimmer/tracking';

export default class extends Component {
    @service membersUtils;
    @service ghostPaths;
    @service ajax;
    @service store;
    @service feature;
    @service settings;

    constructor(...args) {
        super(...args);
        this.member = this.args.member;
        this.scratchMember = this.args.scratchMember;
    }

    @tracked showMemberTierModal = false;
    @tracked tiersList;
    @tracked newslettersList;

    get isAddComplimentaryAllowed() {
        if (!this.membersUtils.paidMembersEnabled) {
            return false;
        }

        if (this.member.get('isNew')) {
            return false;
        }

        if (this.member.get('tiers')?.length > 0) {
            return false;
        }

        // complimentary subscriptions are assigned to tiers so it only
        // makes sense to show the "add complimentary" buttons when there's a
        // tier to assign the complimentary subscription to
        const hasAnActivePaidTier = !!this.tiersList?.length;

        return hasAnActivePaidTier;
    }

    get isCreatingComplimentary() {
        return this.args.isSaveRunning;
    }

    get tiers() {
        let subscriptions = this.member.get('subscriptions') || [];

        // Create the tiers from `subscriptions.price.tier`
        let tiers = subscriptions
            .map(subscription => (subscription.tier || subscription.price.tier))
            .filter((value, index, self) => {
                // Deduplicate by taking the first object by `id`
                return typeof value.id !== 'undefined' && self.findIndex(element => (element.tier_id || element.id) === (value.tier_id || value.id)) === index;
            });

        let subscriptionData = subscriptions.filter((sub) => {
            return !!sub.price;
        }).map((sub) => {
            const data = {
                ...sub,
                attribution: {
                    ...sub.attribution,
                    referrerSource: sub.attribution?.referrer_source || 'Unknown',
                    referrerMedium: sub.attribution?.referrer_medium || '-'
                },
                startDate: sub.start_date ? moment(sub.start_date).format('D MMM YYYY') : '-',
                validUntil: sub.current_period_end ? moment(sub.current_period_end).format('D MMM YYYY') : '-',
                cancellationReason: sub.cancellation_reason,
                price: {
                    ...sub.price,
                    currencySymbol: getSymbol(sub.price.currency),
                    nonDecimalAmount: getNonDecimal(sub.price.amount)
                },
                isComplimentary: !sub.id
            };
            if (sub.trial_end_at) {
                const inTrialMode = moment(sub.trial_end_at).isAfter(new Date(), 'day');
                if (inTrialMode) {
                    data.trialUntil = moment(sub.trial_end_at).format('D MMM YYYY');
                }
            }

            if (!sub.id && sub.tier?.expiry_at) {
                data.compExpiry = moment(sub.tier.expiry_at).utc().format('D MMM YYYY');
            }
            return data;
        });
        return tiers.map((tier) => {
            let tierSubscriptions = subscriptionData.filter((subscription) => {
                return subscription?.price?.tier?.tier_id === (tier.tier_id || tier.id);
            });
            return {
                ...tier,
                subscriptions: tierSubscriptions
            };
        });
    }

    get customer() {
        let firstSubscription = this.member.get('subscriptions').firstObject;
        let customer = firstSubscription?.customer;

        if (customer) {
            return {
                ...customer,
                startDate: firstSubscription?.startDate
            };
        }
        return null;
    }

    get canShowMultipleNewsletters() {
        return (
            this.settings.editorDefaultEmailRecipients !== 'disabled'
        );
    }

    @action
    updateNewsletterPreference(event) {
        if (!event.target.checked) {
            this.member.set('newsletters', []);
        } else if (this.newslettersList.firstObject) {
            const newsletter = this.newslettersList.firstObject;
            this.member.set('newsletters', [newsletter]);
        }
    }

    @action
    setup() {
        this.fetchTiers.perform();
        this.fetchNewsletters.perform();
    }

    @action
    setProperty(property, value) {
        this.args.setProperty(property, value);
    }

    @action
    updateProperty(event){
        this.args.setProperty(event.currentTarget.name, event.target.value);
    }

    @action
    setLabels(labels) {
        this.member.set('labels', labels);
    }

    @action
    setMemberNewsletters(newsletters) {
        this.member.set('newsletters', newsletters);
    }

    @action
    closeMemberTierModal() {
        this.showMemberTierModal = false;
    }

    @action
    cancelSubscription(subscriptionId) {
        this.cancelSubscriptionTask.perform(subscriptionId);
    }

    @action
    removeComplimentary(tierId) {
        this.removeComplimentaryTask.perform(tierId);
    }

    @action
    continueSubscription(subscriptionId) {
        this.continueSubscriptionTask.perform(subscriptionId);
    }

    @task({drop: true})
    *cancelSubscriptionTask(subscriptionId) {
        let url = this.ghostPaths.url.api('members', this.member.get('id'), 'subscriptions', subscriptionId);

        let response = yield this.ajax.put(url, {
            data: {
                cancel_at_period_end: true
            }
        });

        this.store.pushPayload('member', response);
        return response;
    }

    @task({drop: true})
    *removeComplimentaryTask(tierId) {
        let url = this.ghostPaths.url.api(`members/${this.member.get('id')}`);
        let tiers = this.member.get('tiers') || [];

        const updatedTiers = tiers
            .filter(tier => tier.id !== tierId)
            .map(tier => ({id: tier.id}));

        let response = yield this.ajax.put(url, {
            data: {
                members: [{
                    id: this.member.get('id'),
                    email: this.member.get('email'),
                    tiers: updatedTiers
                }]
            }
        });

        this.store.pushPayload('member', response);
        return response;
    }

    @task({drop: true})
    *continueSubscriptionTask(subscriptionId) {
        let url = this.ghostPaths.url.api('members', this.member.get('id'), 'subscriptions', subscriptionId);

        let response = yield this.ajax.put(url, {
            data: {
                cancel_at_period_end: false
            }
        });

        this.store.pushPayload('member', response);
        return response;
    }

    @task({drop: true})
    *fetchTiers() {
        this.tiersList = yield this.store.query('tier', {filter: 'type:paid+active:true', include: 'monthly_price,yearly_price'});
    }

    @task({drop: true})
    *fetchNewsletters() {
        this.newslettersList = yield this.store.query('newsletter', {filter: 'status:active'});
        if (this.member.get('isNew')) {
            const defaultNewsletters = this.newslettersList.filter((newsletter) => {
                return newsletter.subscribeOnSignup && newsletter.visibility === 'members';
            });
            this.setMemberNewsletters(defaultNewsletters);
        }
    }
}
