import { invoke } from "@tauri-apps/api/core";
import { listen, type UnlistenFn } from "@tauri-apps/api/event";
import type {
  NewsSourceConfig,
  QueryNewsFeedRequest,
  QueryNewsFeedResponse,
  RefreshNewsFeedRequest,
  RefreshNewsFeedResult,
  SaveNewsFeedConfigRequest,
  UpdateNewsArticleStateRequest,
} from "../types/news";

type Invoker = <T>(
  command: string,
  args?: Record<string, unknown>,
) => Promise<T>;
type Listener = <T>(
  event: string,
  handler: (event: { payload: T }) => void,
) => Promise<UnlistenFn>;

export interface NewsBridge {
  queryNewsFeed(request: QueryNewsFeedRequest): Promise<QueryNewsFeedResponse>;
  refreshNewsFeed(
    request?: RefreshNewsFeedRequest,
  ): Promise<RefreshNewsFeedResult>;
  getNewsFeedConfig(): Promise<NewsSourceConfig[]>;
  saveNewsFeedConfig(
    request: SaveNewsFeedConfigRequest,
  ): Promise<NewsSourceConfig[]>;
  resetNewsFeedConfig(): Promise<NewsSourceConfig[]>;
  updateNewsArticleState(request: UpdateNewsArticleStateRequest): Promise<void>;
  listenForUpdates(
    handler: (payload: RefreshNewsFeedResult) => void,
  ): Promise<UnlistenFn>;
}

export const createNewsBridge = (
  invoker: Invoker = invoke,
  listener: Listener = listen,
): NewsBridge => ({
  queryNewsFeed(request) {
    return invoker<QueryNewsFeedResponse>("query_news_feed", { request });
  },

  refreshNewsFeed(request = {}) {
    return invoker<RefreshNewsFeedResult>("refresh_news_feed", { request });
  },

  getNewsFeedConfig() {
    return invoker<NewsSourceConfig[]>("get_news_feed_config");
  },

  saveNewsFeedConfig(request) {
    return invoker<NewsSourceConfig[]>("save_news_feed_config", { request });
  },

  resetNewsFeedConfig() {
    return invoker<NewsSourceConfig[]>("reset_news_feed_config");
  },

  updateNewsArticleState(request) {
    return invoker<void>("update_news_article_state", { request });
  },

  listenForUpdates(handler) {
    return listener<RefreshNewsFeedResult>("news_feed_updated", (event) =>
      handler(event.payload),
    );
  },
});

export const newsBridge = createNewsBridge();
