import re

from ..ghost_db import DBClient  # adjust import path
from shared.infrastructure.data_client import fetch_data
from shared.infrastructure.fragments import fetch_fragment
from quart import g

async def posts_data(
    session,
    page, search, sort, selected_tags, selected_authors, liked,
    drafts=False, drafts_user_id=None, count_drafts_for_user_id=None,
    selected_groups=(),
  ):
  client = DBClient(session)

  # --- Tag-group resolution ---
  tag_groups = await client.list_tag_groups_with_counts()

  # Collect all assigned tag IDs across groups
  all_assigned_tag_ids = []
  for grp in tag_groups:
      all_assigned_tag_ids.extend(grp["tag_ids"])

  # Build slug-lookup for groups
  group_by_slug = {grp["slug"]: grp for grp in tag_groups}

  # Resolve selected group → post filtering
  # Groups and tags are mutually exclusive — groups override tags when set
  effective_tags = selected_tags
  etc_mode_tag_ids = None  # set when "etc" is selected
  if selected_groups:
      group_slug = selected_groups[0]
      if group_slug == "etc":
          # etc = posts NOT covered by any group (includes untagged)
          etc_mode_tag_ids = all_assigned_tag_ids
          effective_tags = ()
      elif group_slug in group_by_slug:
          effective_tags = tuple(group_by_slug[group_slug]["tag_slugs"])

  # Compute "etc" virtual group
  etc_count = await client.count_etc_posts(all_assigned_tag_ids)
  if etc_count > 0 or (selected_groups and selected_groups[0] == "etc"):
      tag_groups.append({
          "id": None,
          "name": "etc",
          "slug": "etc",
          "feature_image": None,
          "colour": None,
          "sort_order": 999999,
          "post_count": etc_count,
          "tag_slugs": [],
          "tag_ids": [],
      })

  posts, pagination = await client.list_posts(
      limit=10,
      page=page,
      selected_tags=effective_tags,
      selected_authors=selected_authors,
      search=search,
      drafts=drafts,
      drafts_user_id=drafts_user_id,
      exclude_covered_tag_ids=etc_mode_tag_ids,
  )

  # Get all post IDs in this batch
  post_ids = [p["id"] for p in posts]

  # Add is_liked field to each post for current user
  if g.user and post_ids:
      liked_ids_list = await fetch_data("likes", "liked-ids", params={
          "user_id": g.user.id, "target_type": "post",
      }, required=False) or []
      liked_post_ids = set(liked_ids_list)

      for post in posts:
          post["is_liked"] = post["id"] in liked_post_ids
  else:
      for post in posts:
          post["is_liked"] = False

  # Fetch card decoration fragments from events
  card_widgets_html = {}
  if post_ids:
      post_slugs = [p.get("slug", "") for p in posts]
      cards_html = await fetch_fragment("events", "container-cards", params={
          "post_ids": ",".join(str(pid) for pid in post_ids),
          "post_slugs": ",".join(post_slugs),
      })
      if cards_html:
          card_widgets_html = _parse_card_fragments(cards_html)

  tags=await client.list_tags(
    limit=50000
  )
  authors=await client.list_authors(
    limit=50000
  )

  # Draft count for the logged-in user (None → admin sees all)
  draft_count = 0
  if count_drafts_for_user_id is not False:
      draft_count = await client.count_drafts(user_id=count_drafts_for_user_id)

  return {
      "posts": posts,
      "page": pagination.get("page", page),
      "total_pages": pagination.get("pages", 1),
      "search_count": pagination.get("search_count"),
      "tags": tags,
      "authors": authors,
      "draft_count": draft_count,
      "tag_groups": tag_groups,
      "selected_groups": selected_groups,
      "card_widgets_html": card_widgets_html,
  }


# Regex to extract per-post blocks delimited by comment markers
_CARD_MARKER_RE = re.compile(
    r'<!-- card-widget:(\d+) -->(.*?)<!-- /card-widget:\1 -->',
    re.DOTALL,
)


def _parse_card_fragments(html: str) -> dict[str, str]:
    """Parse the container-cards fragment into {post_id_str: html} dict."""
    result = {}
    for m in _CARD_MARKER_RE.finditer(str(html)):
        post_id_str = m.group(1)
        inner = m.group(2).strip()
        if inner:
            result[post_id_str] = inner
    return result
