// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
/* eslint-disable @typescript-eslint/no-empty-interface */
// Generated by https://quicktype.io
//
// To change quicktype's target language, run command:
//
//   "Set quicktype target language"
import fetch from 'node-fetch'


// Types

export interface Board {
    title: string;
    owner: User;
    color: string;
    archived: boolean;
    labels: Label[];
    acl: any[];
    permissions: {
        PERMISSION_READ: boolean;
        PERMISSION_EDIT: boolean;
        PERMISSION_MANAGE: boolean;
        PERMISSION_SHARE: boolean;
    };
    users: User[];
    shared: number;
    deletedAt: number;
    id: number;
    lastModified: number;
}

export interface Stack {
    title: string;
    boardId: number;
    deletedAt: number;
    lastModified: number;
    cards: Card[];
    order: number;
    id: number;
}

export interface Card {
    title: string;
    description: string;
    stackId: number;
    type: "plain";
    lastModified: number;
    createdAt: number;
    labels: Label[];
    assignedUsers: unknown;
    attachments: unknown;
    attachmentCount: unknown;
    owner: string;
    order: number;
    archived: boolean;
    duedate: string;
    deletedAt: number;
    commentsUnread: number;
    commentsCount: number;
    comments?: Comment[]
    id: number;
    overdue: number;
}

export interface CommentResponse {
    ocs: {
        meta: {
            status: string;
            statuscode: number;
            message: string;
        };
        data: Comment[];
    };
}

export interface Comment {
    id: number;
    objectId: number;
    message: string;
    actorId: string;
    actorType: string;
    actorDisplayName: string;
    creationDateTime: string;
    mentions: [
        {
            mentionId: string;
            mentionType: string;
            mentionDisplayName: string;
        }
    ];
    replyTo?: Comment;
}

export interface Label {
    title: string;
    color: string;
    cardId: any;
    id: number;
}

export interface User {
    primaryKey: string;
    uid: string;
    displayname: string;
}

export interface NextcloudDeckClientConfig {
    url: string
    auth: Auth
}

export interface Auth {
    username: string
    password: string
}

// api

export const defaultHeaders = {
    "OCS-APIRequest": "true",
    "Content-Type": "application/json",
    "Accept": "application/json",
}

export class NextcloudDeckClient {

    config: NextcloudDeckClientConfig

    /**
     * Create a new Nextcloud Deck client
     */
    constructor(config: NextcloudDeckClientConfig) {
        this.config = config
    }

    async fetchWrapper(path: string): Promise<any> {
        const response = await fetch(`${this.config.url}/index.php/apps/deck/api/v1.0/${path}`,
            {
                method: "GET",
                headers: {
                    ...defaultHeaders,
                    "Authorization": 'Basic ' + Buffer.from(`${this.config.auth.username}:${this.config.auth.password}`).toString('base64')
                }
            })
        if (!response.ok) {
            throw new Error(`Request failed with info: ${await response.text()}`)
        }
        return await response.json()
    }
    async fetchWrapperOCS(path: string): Promise<any> {
        const response = await fetch(`${this.config.url}/ocs/v2.php/apps/deck/api/v1.0/${path}`,
            {
                method: "GET",
                headers: {
                    ...defaultHeaders,
                    "Authorization": 'Basic ' + Buffer.from(`${this.config.auth.username}:${this.config.auth.password}`).toString('base64')
                }
            })
        if (!response.ok) {
            throw new Error(`Request failed with info: ${await response.text()}`)
        }
        return await response.json()
    }

    async getBoards(): Promise<Board[]> {
        return await this.fetchWrapper('boards')
    }

    async getBoardDetails(boardId: number): Promise<Board> {
        return await this.fetchWrapper(`boards/${boardId}`)

    }

    async getStacks(boardId: number): Promise<Stack[]> {
        return await this.fetchWrapper(`boards/${boardId}/stacks`)

    }

    async getStacksArchived(boardId: number): Promise<Stack[]> {
        return await this.fetchWrapper(`boards/${boardId}/stacks/archived`)

    }

    async getStackDetails(boardId: number, stackId: number): Promise<Stack> {
        return await this.fetchWrapper(`boards/${boardId}/stacks/${stackId}`)

    }

    async getCardDetails(boardId: number, stackId: number, cardId: number): Promise<Card[]> {
        return await this.fetchWrapper(`boards/${boardId}/stacks/${stackId}/cards/${cardId}`)

    }

    async getComments(cardId: number): Promise<Comment[]> {
        const response = await this.fetchWrapperOCS(`cards/${cardId}/comments`) as CommentResponse
        return response.ocs.data
    }
}

