import { NewsData, NewsFeed } from "../pages/feed/news";
import { NewsItem } from "../pages/feed/news-item";

type EndpointURL = "" | `http${'s' | ''}://${string}`;

interface ErrorDetails {
    code: string,
    message: string,
}

interface APIResponse<T> {
    response ?: T;
    error ?: ErrorDetails;
}

let newsFeed : NewsFeed | null = null;

class ErrorAPI extends Error {}

export class ControllerAPI {
    protected endpoint: EndpointURL;
    constructor(endpoint: EndpointURL = "") {
        this.endpoint = endpoint;
    }

    protected async request<T>(path: string, options: RequestInit = {}): Promise<T> {
        const url = new URL(path, this.endpoint || window.location.origin).href;

        const response = await fetch(url, options);
        const result: APIResponse<T> = await response.json();
        if (result.error) throw new ErrorAPI(result.error.message);
        if (result.response === undefined) throw new ErrorAPI("Missing response from API");
        return result.response;
    }

    protected checkFirstAuth(): boolean {
        // Implement your authentication logic here, e.g., check for a valid token in localStorage
        //const token = localStorage.getItem('authToken');
        //return !!token; // Returns true if token exists and is not empty
        return true;
    }

    protected throwIfUnauthed(): void {
        // Let's redirect to /auth if not authed
        if (!this.checkFirstAuth()) {
            window.location.href = '/auth';
        }
    }

    async isAuthenticated(): Promise<boolean> {
        if (!this.checkFirstAuth()) return false;

        const result = await this.request<boolean>('/api/isAuthenticated', {
            method: 'GET',
            credentials: 'include' // Include cookies for authentication
        });
        return result;
    }

    async getNews(returnElement: boolean = false) : Promise<NewsFeed | NewsData[]> {
        this.throwIfUnauthed();
        
        const result = await this.request<NewsData[]>('/api/news', {
            method: 'GET',
            credentials: 'include' // Include cookies for authentication
        });
        if (!returnElement)
            return result;
        if (!newsFeed)
            newsFeed = new NewsFeed(result.map(x => new NewsItem(x.title, new Date(x.publishedAt), x.content)));
        return newsFeed;
    }
}