import { Config, ConfigProvider, Data, Effect } from "effect";
import { getAiHeroAccessToken } from "@/services/ai-hero-auth-service";
import { FeatureFlagService } from "@/services/feature-flag-service";

export class AiHeroShortLinkError extends Data.TaggedError(
  "AiHeroShortLinkError"
)<{
  message: string;
  code?: string;
}> {}

type ShortLink = {
  id: string;
  slug: string;
  url: string;
  description: string | null;
};

/**
 * Create a short link on AI Hero.
 * Slug is auto-generated by the API.
 */
const createShortLink = (opts: {
  baseUrl: string;
  accessToken: string;
  url: string;
  description: string;
}) =>
  Effect.tryPromise({
    try: async () => {
      const res = await fetch(`${opts.baseUrl}/api/shortlinks`, {
        method: "POST",
        headers: {
          Authorization: `Bearer ${opts.accessToken}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          url: opts.url,
          description: opts.description,
        }),
      });

      if (!res.ok) {
        const errorText = await res.text();
        throw new Error(
          `Failed to create short link (${res.status}): ${errorText}`
        );
      }

      return (await res.json()) as ShortLink;
    },
    catch: (e) =>
      new AiHeroShortLinkError({
        message: e instanceof Error ? e.message : "Failed to create short link",
        code: "create_shortlink_failed",
      }),
  });

/**
 * Search for short links by query string.
 * Uses GET /api/shortlinks?search={query}.
 */
const searchShortLinks = (opts: {
  baseUrl: string;
  accessToken: string;
  query: string;
}) =>
  Effect.tryPromise({
    try: async () => {
      const res = await fetch(
        `${opts.baseUrl}/api/shortlinks?search=${encodeURIComponent(opts.query)}`,
        {
          headers: {
            Authorization: `Bearer ${opts.accessToken}`,
          },
        }
      );

      if (!res.ok) {
        const errorText = await res.text();
        throw new Error(
          `Failed to search short links (${res.status}): ${errorText}`
        );
      }

      return (await res.json()) as ShortLink[];
    },
    catch: (e) =>
      new AiHeroShortLinkError({
        message:
          e instanceof Error ? e.message : "Failed to search short links",
        code: "search_shortlinks_failed",
      }),
  });

/**
 * Find an existing short link by matching on description, or create a new one.
 * Returns the short link URL in the format https://aihero.dev/s/{slug}.
 */
export const findOrCreateShortLink = (opts: {
  url: string;
  description: string;
}) =>
  Effect.gen(function* () {
    const baseUrl = yield* Config.string("AI_HERO_BASE_URL");
    const accessToken = yield* getAiHeroAccessToken;
    const featureFlags = yield* FeatureFlagService;

    if (featureFlags.isEnabled("ENABLE_SHORTLINK_SEARCH")) {
      // Search for existing short link with matching description
      const existing = yield* searchShortLinks({
        baseUrl,
        accessToken,
        query: opts.description,
      });

      const match = existing.find((sl) => sl.description === opts.description);

      if (match) {
        return { shortLinkUrl: `https://aihero.dev/s/${match.slug}` };
      }
    }

    // Create a new short link
    const created = yield* createShortLink({
      baseUrl,
      accessToken,
      url: opts.url,
      description: opts.description,
    });

    return { shortLinkUrl: `https://aihero.dev/s/${created.slug}` };
  }).pipe(Effect.withConfigProvider(ConfigProvider.fromEnv()));
