import { query } from "../_generated/server";
import { v } from "convex/values";
import { contentStatusValidator } from "../schema/content";

// ── Blog Queries ──────────────────────────────────────────────────────

/**
 * Get all blog posts for a specific language (metadata only, no content)
 */
export const getAllPosts = query({
  args: {
    lang: v.string(),
    published: v.optional(v.boolean()),
  },
  handler: async (ctx, args) => {
    const lang = args.lang;
    const published = args.published ?? true;
    const posts = await ctx.db
      .query("blog_posts")
      .withIndex("by_lang_published", (q) =>
        q.eq("lang", lang).eq("published", published),
      )
      .collect();
    // Sort by date descending (newest first)
    posts.sort((a, b) =>
      (b.date ?? "") > (a.date ?? "")
        ? 1
        : (b.date ?? "") < (a.date ?? "")
          ? -1
          : 0,
    );
    return posts;
  },
});

/**
 * Get a single blog post by slug and language (includes content)
 */
export const getPostBySlug = query({
  args: {
    slug: v.string(),
    lang: v.string(),
  },
  handler: async (ctx, args) => {
    const post = await ctx.db
      .query("blog_posts")
      .withIndex("by_slug_lang", (q) =>
        q.eq("slug", args.slug).eq("lang", args.lang),
      )
      .first();
    return post ?? null;
  },
});

/**
 * Get paginated blog posts (published only)
 */
export const getPaginatedPosts = query({
  args: {
    lang: v.string(),
    page: v.optional(v.number()),
    postsPerPage: v.optional(v.number()),
    tag: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    const lang = args.lang;
    const page = args.page ?? 1;
    const postsPerPage = args.postsPerPage ?? 9;

    let posts = await ctx.db
      .query("blog_posts")
      .withIndex("by_lang_published", (q) =>
        q.eq("lang", lang).eq("published", true),
      )
      .collect();

    // Optional tag filter
    if (args.tag) {
      posts = posts.filter((p) => p.tags.includes(args.tag!));
    }

    // Sort by date descending
    posts.sort((a, b) =>
      (b.date ?? "") > (a.date ?? "")
        ? 1
        : (b.date ?? "") < (a.date ?? "")
          ? -1
          : 0,
    );

    const totalPosts = posts.length;
    const totalPages = Math.ceil(totalPosts / postsPerPage);
    const validPage = Math.max(1, Math.min(page, totalPages || 1));
    const start = (validPage - 1) * postsPerPage;
    const paged = posts.slice(start, start + postsPerPage);

    return {
      posts: paged,
      totalPages,
      totalPosts,
      currentPage: validPage,
    };
  },
});

/**
 * Get all unique tags from published posts
 */
export const getAllTags = query({
  args: {
    lang: v.string(),
  },
  handler: async (ctx, args) => {
    const posts = await ctx.db
      .query("blog_posts")
      .withIndex("by_lang_published", (q) =>
        q.eq("lang", args.lang).eq("published", true),
      )
      .collect();

    const tagSet = new Set<string>();
    for (const post of posts) {
      for (const tag of post.tags) {
        tagSet.add(tag);
      }
    }
    return Array.from(tagSet).sort();
  },
});

/**
 * Get posts by tag (published only)
 */
export const getPostsByTag = query({
  args: {
    tag: v.string(),
    lang: v.string(),
  },
  handler: async (ctx, args) => {
    const posts = await ctx.db
      .query("blog_posts")
      .withIndex("by_lang_published", (q) =>
        q.eq("lang", args.lang).eq("published", true),
      )
      .collect();

    const filtered = posts.filter((p) => p.tags.includes(args.tag));
    filtered.sort((a, b) =>
      (b.date ?? "") > (a.date ?? "")
        ? 1
        : (b.date ?? "") < (a.date ?? "")
          ? -1
          : 0,
    );
    return filtered;
  },
});

/**
 * Get related posts based on shared tags (excludes current post)
 */
export const getRelatedPosts = query({
  args: {
    currentSlug: v.string(),
    lang: v.string(),
    limit: v.optional(v.number()),
  },
  handler: async (ctx, args) => {
    const limit = args.limit ?? 3;

    // Get current post tags
    const currentPost = await ctx.db
      .query("blog_posts")
      .withIndex("by_slug_lang", (q) =>
        q.eq("slug", args.currentSlug).eq("lang", args.lang),
      )
      .first();

    if (!currentPost || !currentPost.tags || currentPost.tags.length === 0) {
      return [];
    }

    const currentTags = currentPost.tags;

    // Get all published posts except current
    const allPosts = await ctx.db
      .query("blog_posts")
      .withIndex("by_lang_published", (q) =>
        q.eq("lang", args.lang).eq("published", true),
      )
      .collect();

    // Score by shared tags, exclude current post
    const scored = allPosts
      .filter((p) => p.slug !== args.currentSlug)
      .map((post) => {
        const sharedCount = post.tags.filter((t) =>
          currentTags.includes(t),
        ).length;
        return { post, score: sharedCount };
      })
      .filter((item) => item.score > 0)
      .sort((a, b) => b.score - a.score)
      .slice(0, limit)
      .map((item) => item.post);

    return scored;
  },
});

/**
 * Get all post slugs for static generation
 */
export const getAllPostSlugs = query({
  args: {
    lang: v.string(),
  },
  handler: async (ctx, args) => {
    const posts = await ctx.db
      .query("blog_posts")
      .withIndex("by_lang_published", (q) =>
        q.eq("lang", args.lang).eq("published", true),
      )
      .collect();
    return posts.map((p) => p.slug);
  },
});

/**
 * Get blog metadata (aggregate stats)
 */
export const getBlogMetadata = query({
  args: {
    lang: v.string(),
  },
  handler: async (ctx, args) => {
    const posts = await ctx.db
      .query("blog_posts")
      .withIndex("by_lang_published", (q) =>
        q.eq("lang", args.lang).eq("published", true),
      )
      .collect();

    const tagSet = new Set<string>();
    for (const post of posts) {
      for (const tag of post.tags) {
        tagSet.add(tag);
      }
    }

    return {
      totalPosts: posts.length,
      totalTags: tagSet.size,
      tags: Array.from(tagSet).sort(),
    };
  },
});

// ── CMS Content Queries ───────────────────────────────────────────────

/**
 * Get hero sections by language and status
 * Phase 8: Content, Careers, Real Estate, Analytics, Reviews
 */
export const getHeroSections = query({
  args: {
    lang: v.optional(v.string()),
    status: v.optional(contentStatusValidator),
  },
  handler: async (ctx, args) => {
    const lang = args.lang ?? "en";
    const status = args.status ?? "PUBLISHED";
    return await ctx.db
      .query("hero_sections")
      .withIndex("by_lang_status", (q) =>
        q.eq("lang", lang).eq("status", status),
      )
      .collect();
  },
});

/**
 * Get feature blocks by language and status
 * Phase 8: Content, Careers, Real Estate, Analytics, Reviews
 */
export const getFeatureBlocks = query({
  args: {
    lang: v.optional(v.string()),
    status: v.optional(contentStatusValidator),
  },
  handler: async (ctx, args) => {
    const lang = args.lang ?? "en";
    const status = args.status ?? "PUBLISHED";
    return await ctx.db
      .query("feature_blocks")
      .withIndex("by_lang_status", (q) =>
        q.eq("lang", lang).eq("status", status),
      )
      .collect();
  },
});

/**
 * Get active announcements for a page/role
 * Phase 8: Content, Careers, Real Estate, Analytics, Reviews
 */
export const getAnnouncements = query({
  args: {
    lang: v.optional(v.string()),
    status: v.optional(contentStatusValidator),
  },
  handler: async (ctx, args) => {
    const lang = args.lang ?? "en";
    const status = args.status ?? "PUBLISHED";
    const now = Date.now();
    return await ctx.db
      .query("announcements")
      .withIndex("by_lang_status", (q) =>
        q.eq("lang", lang).eq("status", status),
      )
      .filter((f) =>
        f.and(
          f.or(
            f.eq(f.field("startAt"), undefined),
            f.lte(f.field("startAt"), now),
          ),
          f.or(f.eq(f.field("endAt"), undefined), f.gte(f.field("endAt"), now)),
        ),
      )
      .collect();
  },
});
