import {
  starterRouteFetch,
  wordpressRestFetch,
} from "@/lib/wordpress-client";
import type {
  StorefrontBlogArchivePage,
  StorefrontBlogPost,
  StorefrontBlogPostCard,
  StorefrontImage,
  StorefrontTerm,
} from "@/types/storefront";

interface StarterBlogTermResponse {
  id?: number;
  name?: string;
  slug?: string;
}

interface StarterBlogImageResponse {
  src?: string;
  alt?: string;
}

interface StarterBlogPostCardResponse {
  id?: number;
  slug?: string;
  href?: string;
  title?: string;
  excerpt?: string;
  publishedAt?: string;
  category?: StarterBlogTermResponse | null;
  image?: StarterBlogImageResponse | null;
}

interface StarterBlogArchiveResponse {
  title?: string;
  query?: string;
  currentCategorySlug?: string;
  totalResults?: number;
  currentPage?: number;
  totalPages?: number;
  categories?: StarterBlogTermResponse[];
  posts?: StarterBlogPostCardResponse[];
}

interface StarterBlogPostResponse extends StarterBlogPostCardResponse {
  authorName?: string;
  authorAvatar?: StarterBlogImageResponse | null;
  contentHtml?: string;
  relatedPosts?: StarterBlogPostCardResponse[];
}

interface WordPressRenderedField {
  rendered?: string;
}

interface WordPressEmbeddedMedia {
  source_url?: string;
  alt_text?: string;
}

interface WordPressEmbeddedTerm {
  id?: number;
  name?: string;
  slug?: string;
  taxonomy?: string;
}

interface WordPressBlogPostResponse {
  id?: number;
  slug?: string;
  date?: string;
  title?: WordPressRenderedField;
  excerpt?: WordPressRenderedField;
  content?: WordPressRenderedField;
  _embedded?: {
    ["wp:featuredmedia"]?: Array<WordPressEmbeddedMedia>;
    ["wp:term"]?: Array<Array<WordPressEmbeddedTerm>>;
  };
}

interface WordPressBlogCategoryResponse {
  id?: number;
  name?: string;
  slug?: string;
}

function stripHtml(value?: string) {
  return (value ?? "").replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim();
}

function mapImage(image?: StarterBlogImageResponse | null): StorefrontImage | null {
  if (!image?.src?.trim()) {
    return null;
  }

  return {
    src: image.src.trim(),
    alt: image.alt?.trim() || "",
  };
}

function mapTerm(term?: StarterBlogTermResponse | null): StorefrontTerm | null {
  if (
    typeof term?.id !== "number" ||
    !term.name?.trim() ||
    !term.slug?.trim()
  ) {
    return null;
  }

  return {
    id: term.id,
    name: term.name.trim(),
    slug: term.slug.trim(),
  };
}

function mapBlogPostCard(
  post?: StarterBlogPostCardResponse | null,
): StorefrontBlogPostCard | null {
  if (
    typeof post?.id !== "number" ||
    !post.slug?.trim() ||
    !post.href?.trim() ||
    !post.title?.trim()
  ) {
    return null;
  }

  return {
    id: post.id,
    slug: post.slug.trim(),
    href: post.href.trim(),
    title: post.title.trim(),
    excerpt: post.excerpt?.trim() || "",
    publishedAt: post.publishedAt?.trim() || "",
    category: mapTerm(post.category),
    image: mapImage(post.image),
  };
}

function mapArchiveResponse(
  archive?: StarterBlogArchiveResponse | null,
): StorefrontBlogArchivePage {
  return {
    title: archive?.title?.trim() || "Blog",
    query: archive?.query?.trim() || "",
    currentCategorySlug: archive?.currentCategorySlug?.trim() || "",
    totalResults: Math.max(0, archive?.totalResults ?? 0),
    currentPage: Math.max(1, archive?.currentPage ?? 1),
    totalPages: Math.max(1, archive?.totalPages ?? 1),
    categories: (archive?.categories ?? [])
      .map(mapTerm)
      .filter((term): term is StorefrontTerm => term !== null),
    posts: (archive?.posts ?? [])
      .map(mapBlogPostCard)
      .filter((post): post is StorefrontBlogPostCard => post !== null),
  };
}

function mapFeaturedImage(post: WordPressBlogPostResponse): StorefrontImage | null {
  const image = post._embedded?.["wp:featuredmedia"]?.[0];

  if (!image?.source_url?.trim()) {
    return null;
  }

  return {
    src: image.source_url.trim(),
    alt: image.alt_text?.trim() || "",
  };
}

function mapEmbeddedCategory(post: WordPressBlogPostResponse): StorefrontTerm | null {
  const groups = post._embedded?.["wp:term"] ?? [];

  for (const group of groups) {
    for (const term of group) {
      if (
        term?.taxonomy === "kategorije-blogova" &&
        typeof term.id === "number" &&
        term.name?.trim() &&
        term.slug?.trim()
      ) {
        return {
          id: term.id,
          name: term.name.trim(),
          slug: term.slug.trim(),
        };
      }
    }
  }

  return null;
}

function mapWordPressPostCard(
  post?: WordPressBlogPostResponse | null,
): StorefrontBlogPostCard | null {
  if (
    typeof post?.id !== "number" ||
    !post.slug?.trim() ||
    !post.title?.rendered
  ) {
    return null;
  }

  return {
    id: post.id,
    slug: post.slug.trim(),
    href: `/blog/${post.slug.trim()}`,
    title: stripHtml(post.title.rendered),
    excerpt: stripHtml(post.excerpt?.rendered),
    publishedAt: post.date?.trim() || "",
    category: mapEmbeddedCategory(post),
    image: mapFeaturedImage(post),
  };
}

async function getFallbackBlogCategories(): Promise<StorefrontTerm[]> {
  try {
    const terms = await wordpressRestFetch<WordPressBlogCategoryResponse[]>(
      "/wp/v2/kategorije-blogova?per_page=100",
      { cache: "force-cache" },
    );

    return terms
      .map((term) => mapTerm(term))
      .filter((term): term is StorefrontTerm => term !== null);
  } catch {
    return [];
  }
}

async function getFallbackArchive({
  page = 1,
  perPage = 9,
  query = "",
  category = "",
}: {
  page?: number;
  perPage?: number;
  query?: string;
  category?: string;
}): Promise<StorefrontBlogArchivePage> {
  const categories = await getFallbackBlogCategories();
  const selectedCategory = categories.find((item) => item.slug === category);
  const params = new URLSearchParams({
    per_page: String(Math.max(1, Math.min(24, perPage))),
    page: String(Math.max(1, page)),
    _embed: "wp:featuredmedia,wp:term",
  });

  if (query.trim()) {
    params.set("search", query.trim());
  }

  if (selectedCategory) {
    params.set("kategorije-blogova", String(selectedCategory.id));
  }

  try {
    const posts = await wordpressRestFetch<WordPressBlogPostResponse[]>(
      `/wp/v2/blog?${params.toString()}`,
      { cache: "no-store" },
    );

    return {
      title: "Savjeti i novosti",
      query: query.trim(),
      currentCategorySlug: category.trim(),
      totalResults: posts.length,
      currentPage: Math.max(1, page),
      totalPages: Math.max(1, posts.length === perPage ? page + 1 : page),
      categories,
      posts: posts
        .map(mapWordPressPostCard)
        .filter((post): post is StorefrontBlogPostCard => post !== null),
    };
  } catch {
    return {
      title: "Savjeti i novosti",
      query: query.trim(),
      currentCategorySlug: category.trim(),
      totalResults: 0,
      currentPage: Math.max(1, page),
      totalPages: 1,
      categories,
      posts: [],
    };
  }
}

export async function getBlogArchive({
  page = 1,
  perPage = 9,
  query = "",
  category = "",
}: {
  page?: number;
  perPage?: number;
  query?: string;
  category?: string;
} = {}): Promise<StorefrontBlogArchivePage> {
  const params = new URLSearchParams({
    page: String(Math.max(1, page)),
    per_page: String(Math.max(1, Math.min(24, perPage))),
  });

  if (query.trim()) {
    params.set("q", query.trim());
  }

  if (category.trim()) {
    params.set("category", category.trim());
  }

  try {
    const archive = await starterRouteFetch<StarterBlogArchiveResponse>(
      `/blog-archive?${params.toString()}`,
      { cache: "force-cache" },
    );

    return mapArchiveResponse(archive);
  } catch {
    return getFallbackArchive({ page, perPage, query, category });
  }
}

export async function getBlogPosts(limit = 9): Promise<StorefrontBlogPostCard[]> {
  const archive = await getBlogArchive({ perPage: limit });
  return archive.posts;
}

export async function getBlogPostBySlug(
  slug: string,
): Promise<StorefrontBlogPost | null> {
  try {
    const post = await starterRouteFetch<StarterBlogPostResponse>(
      `/blog-post?slug=${encodeURIComponent(slug)}`,
      { cache: "no-store" },
    );
    const card = mapBlogPostCard(post);

    if (!card || !post.contentHtml?.trim()) {
      return null;
    }

    return {
      ...card,
      authorName: post.authorName?.trim() || "",
      authorAvatar: mapImage(post.authorAvatar),
      contentHtml: post.contentHtml.trim(),
      relatedPosts: (post.relatedPosts ?? [])
        .map(mapBlogPostCard)
        .filter((item): item is StorefrontBlogPostCard => item !== null),
    };
  } catch {
    try {
      const posts = await wordpressRestFetch<WordPressBlogPostResponse[]>(
        `/wp/v2/blog?slug=${encodeURIComponent(slug)}&_embed=wp:featuredmedia,wp:term`,
        { cache: "no-store" },
      );
      const post = posts[0];
      const card = post ? mapWordPressPostCard(post) : null;

      if (!post || !card || !post.content?.rendered) {
        return null;
      }

      return {
        ...card,
        authorName: "",
        authorAvatar: null,
        contentHtml: post.content.rendered,
        relatedPosts: [],
      };
    } catch {
      return null;
    }
  }
}
