import {Injectable} from '@angular/core';
import {EMPTY, expand, map, Observable, reduce, take} from "rxjs";
import {MastodonApiListsService} from "../../../../../mastodon-api/src/lib/services/mastodon-api-lists.service";
import {PersistentStore} from "../state/persistent/persistent-store.service";
import {Account} from "../../../../../mastodon-api/src/lib/interfaces/public/account";
import {List} from "../../../../../mastodon-api/src/lib/interfaces/public/list";

@Injectable({
    providedIn: 'root'
})
export class ListService {

    constructor(private mastodonApiListsService: MastodonApiListsService,
                private store: PersistentStore) {
    }

    loadLists(): Observable<List[]> {
        const applicationState = this.store.value;
        const instanceName = applicationState.currentInstance?.instanceName;
        const accessToken = applicationState.currentInstance?.accessToken;
        return this.mastodonApiListsService
            .getLists(instanceName, accessToken!)
            .pipe(map(result => result.sort((a, b) => a.title.localeCompare(b.title))));
    }


    createList(title: string) {
        const applicationState = this.store.value;
        const instanceName = applicationState.currentInstance?.instanceName;
        const accessToken = applicationState.currentInstance?.accessToken;
        return this.mastodonApiListsService
            .createList(instanceName, accessToken!, title)
            .pipe(
                take(1),
            );
    }

    updateList(listId: string, newName: string) {
        const applicationState = this.store.value;
        const instanceName = applicationState.currentInstance?.instanceName;
        const accessToken = applicationState.currentInstance?.accessToken;
        return this.mastodonApiListsService
            .updateList(instanceName, accessToken!, listId, newName)
            .pipe(
                take(1),
            );
    }


    loadAccountsIdsForList(listId: string): Observable<{ [id: string]: string[] }> {
        const applicationState = this.store.value;
        const instanceName = applicationState.currentInstance?.instanceName;
        const accessToken = applicationState.currentInstance?.accessToken;
        return this.mastodonApiListsService
            .getAccountsForList(instanceName, accessToken!, listId)
            .pipe(
                expand(result => {
                    const nextLink = result[0];
                    if (nextLink && nextLink.length > 0) {
                        return this.mastodonApiListsService.getAccountsForList(instanceName, accessToken!, listId, nextLink);
                    }
                    return EMPTY;
                }),
                map(result => {
                        const accounts = result[1];
                        return {[listId]: accounts.map(account => account.id)};
                    }
                ),
                reduce((acc: { [listId: string]: string[] }, res: { [listId: string]: string[] }) => {
                    const listId = Object.keys(res)[0];
                    if (acc[listId] !== undefined && acc[listId].length > 0) {
                        acc[listId] = acc[listId].concat(res[listId]);
                        return acc;
                    }
                    return {...acc, ...res};
                }, {}),
            );
    }

    addAccountToSelectedList(accountId: string, listId: string) {
        const applicationState = this.store.value;
        const instanceName = applicationState.currentInstance?.instanceName;
        const accessToken = applicationState.currentInstance?.accessToken;
        return this.mastodonApiListsService
            .addAccountToList(instanceName, accessToken!, listId, accountId)
            .pipe(
                take(1),
            );
    }

    removeAccountFromList(accountId: string, listId: string) {
        const applicationState = this.store.value;
        const instanceName = applicationState.currentInstance?.instanceName;
        const accessToken = applicationState.currentInstance?.accessToken;
        return this.mastodonApiListsService
            .removeAccountFromList(instanceName, accessToken!, listId, accountId)
            .pipe(
                take(1),
            )
    }
}

