import type { NitterPluginConfig } from "./config.js";
import type { FeedSubscription } from "./feed-state.js";
import type { NitterRssItem } from "./rss.js";

export type DeliveryApi = {
  enqueueSystemEvent: (text: string, options: { sessionKey: string; contextKey?: string }) => void;
  logger: {
    info: (msg: string) => void;
    warn: (msg: string) => void;
    error: (msg: string) => void;
  };
};

export type DeliveryResult = {
  sessionDelivered: boolean;
  channelDelivered: boolean;
  itemCount: number;
};

export function formatRelativeTime(ms: number): string {
  const now = Date.now();
  const diff = now - ms;
  if (diff < 0) return "just now";

  const minutes = Math.floor(diff / 60_000);
  if (minutes < 1) return "just now";
  if (minutes < 60) return `${minutes}m ago`;

  const hours = Math.floor(minutes / 60);
  if (hours < 24) return `${hours}h ago`;

  const days = Math.floor(hours / 24);
  if (days < 30) return `${days}d ago`;

  const months = Math.floor(days / 30);
  if (months < 12) return `${months}mo ago`;

  const years = Math.floor(months / 12);
  return `${years}y ago`;
}

export function formatFeedDigest(items: NitterRssItem[], subscription: FeedSubscription): string {
  const { username, label } = subscription;
  const header = label ? `[Nitter: ${label} (@${username})]` : `[Nitter: @${username}]`;

  const displayItems = items.slice(0, 10);
  const lines: string[] = [header, ""];

  for (const item of displayItems) {
    const prefix = item.isRetweet ? "RT " : item.isReply ? "\u21a9 " : "";
    const content = item.content.length > 280 ? `${item.content.slice(0, 280)}...` : item.content;
    const timestamp = formatRelativeTime(item.pubDateMs);

    lines.push(`${prefix}${content}`);
    lines.push(`${item.link} (${timestamp})`);
    lines.push("");
  }

  if (items.length > 10) {
    lines.push(`${items.length} new tweet(s)`);
  }

  return lines.join("\n").trimEnd();
}

export function deliverFeedItems(params: {
  items: NitterRssItem[];
  subscription: FeedSubscription;
  config: NitterPluginConfig;
  api: DeliveryApi;
  sessionKey?: string;
}): DeliveryResult {
  const { items, subscription, config, api, sessionKey } = params;

  const result: DeliveryResult = {
    sessionDelivered: false,
    channelDelivered: false,
    itemCount: items.length,
  };

  if (items.length === 0) return result;

  const digest = formatFeedDigest(items, subscription);

  // Session delivery
  if ((config.deliveryMode === "session" || config.deliveryMode === "both") && sessionKey) {
    api.enqueueSystemEvent(digest, { sessionKey, contextKey: "nitter-feed" });
    result.sessionDelivered = true;
  }

  // Channel delivery: when mode is "channel", or when mode is "both" and session delivery didn't happen
  if (
    config.deliveryMode === "channel" ||
    (config.deliveryMode === "both" && !result.sessionDelivered)
  ) {
    const channel = subscription.deliveryChannel ?? config.deliveryChannel;
    const to = subscription.deliveryTo ?? config.deliveryTo;

    if (channel && to) {
      api.logger.info(`[nitter] channel delivery: ${channel} -> ${to} (${items.length} items)`);
      result.channelDelivered = true;
    } else {
      api.logger.warn(
        `[nitter] channel delivery skipped: missing channel or to for @${subscription.username}`,
      );
    }
  }

  return result;
}
