import {Injectable} from '@angular/core';
import {catchError, map, Observable, of, throwError} from "rxjs";
import {RegisterAppResponse} from "../interfaces/responses/register_app_response";
import {GetAccessTokenResponse} from "../interfaces/responses/get_access_token_response";
import {VerifyCredentialsResponse} from "../interfaces/responses/verify_credentials_response";
import {MastodonApiService} from "./mastodon-api.service";
import {RegisteredApp} from "../interfaces/public/registered_app";

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

    constructor(private mastodonApiService: MastodonApiService) {
    }

    createApp(instance: string, clientName: string, redirectUrl: string, website: string): Observable<RegisteredApp> {
        const scopes = ['read', 'write']; // no 'follow'

        const parameters: {
            client_name: string,
            redirect_uris: string,
            scopes: string,
            website: string
        } = {
            client_name: clientName,
            redirect_uris: redirectUrl,
            scopes: scopes.join(' '),
            website
        }
        const url = `https://${instance}/api/v1/apps`;
        return this.mastodonApiService
            .post<RegisterAppResponse>(url, parameters)
            .pipe(
                map((response) => {
                    return <RegisteredApp>{
                        id: response.id,
                        name: response.name,
                        website: response.website,
                        redirectUri: response.redirect_uri,
                        clientId: response.client_id,
                        clientSecret: response.client_secret,
                        vapidKey: response.vapid_key,
                    }
                }),
                catchError((error) => throwError(error)),
            );
    }

    authorizeUser(instance: string, clientId: string, redirectUrl: string) {
        const parameters = [
            ['response_type', 'code'].join("="),
            ['scope', 'read write'].join("="),
            ['client_id', clientId].join("="),
            ['redirect_uri', redirectUrl].join("="),
        ].join("&");
        window.location.href = `https://${instance}/oauth/authorize?${parameters}`;
    }

    verifyCredentials(instance: string, accessToken: string): Observable<string> {
        const url = `https://${instance}/api/v1/accounts/verify_credentials`;
        return this.mastodonApiService
            .getAuthenticated<VerifyCredentialsResponse>(url, accessToken)
            .pipe(map((response) => response.id));

    }

    getAccessToken(instanceName: string, clientId: string, clientSecret: string, redirectUrl: string, code: string): Observable<string> {
        const parameters: {
            client_id: string,
            client_secret: string,
            redirect_uri: string,
            grant_type: string,
            code: string,
            scope: string
        } = {
            client_id: clientId,
            client_secret: clientSecret,
            redirect_uri: redirectUrl,
            grant_type: 'authorization_code',
            code: code,
            scope: 'read write'
        }
        const url = `https://${instanceName}/oauth/token`;
        return this.mastodonApiService
            .post<GetAccessTokenResponse>(url, parameters)
            .pipe(map((response) => response.access_token));
    }
}
