const { div, h2, h3, p, section, button, form, a, input, img, label, select, option, br, textarea, h1, span, nav, ul, li, video, audio, table, tr, td, thead, tbody, th } = require("../server/node_modules/hyperaxe");
const moment = require("../server/node_modules/moment");
const { template, i18n, userLink, renderStateChip, renderPrivacyChip, renderLifespanChip, renderModeChip, renderInviteQrCard, renderContentActions } = require('./main_views');
const { renderEncryptedChip: renderTribeEncryptedChip } = require('./clearnet_view');
const { renderResults: renderPollResults, renderBallot: renderPollBallot } = require('./polls_view');
const { config } = require('../server/SSB_server.js');
const { renderUrl } = require('../backend/renderUrl');
const { renderMapLocationUrl, renderMapLocationGrid, renderMapLocationVisitLabel } = require("./maps_view");
const opinion_categories = require('../backend/opinion_categories.js');

const userId = config.keys.id;
const isLarpHouseTribe = (t) => Array.isArray(t && t.tags) && t.tags.some(x => String(x).startsWith('larp-'));

const DEFAULT_HASH_ENC = "%260000000000000000000000000000000000000000000%3D.sha256";
const DEFAULT_HASH_PATH_RE = /\/image\/\d+\/%260000000000000000000000000000000000000000000%3D\.sha256$/;
const isDefaultImageId = (v) => {
  if (!v) return true;
  if (typeof v === 'string') {
    if (v === DEFAULT_HASH_ENC) return true;
    if (DEFAULT_HASH_PATH_RE.test(v)) return true;
  }
  return false;
};
const resolvePhoto = (photoField) => {
  if (!photoField) return '/assets/images/default-avatar.png';
  if (typeof photoField === 'string') {
    if (photoField.startsWith('/assets/')) return photoField;
    if (photoField.startsWith('/blob/')) return photoField;
    if (photoField.startsWith('/image/')) {
      if (isDefaultImageId(photoField)) return '/assets/images/default-avatar.png';
      return photoField;
    }
  }
  return '/assets/images/default-avatar.png';
};

const MS_PER_DAY = 86400000;
const FEED_ITEMS_PER_PAGE = 5;
const MAX_MESSAGE_LENGTH = 280;

const renderMediaBlob = (value, fallbackSrc = null, attrs = {}) => {
  if (!value) return fallbackSrc ? img({ src: fallbackSrc, ...attrs }) : null
  const s = String(value).trim()
  if (!s) return fallbackSrc ? img({ src: fallbackSrc, ...attrs }) : null
  if (s.startsWith('/assets/') || s.startsWith('/blob/') || s.startsWith('/image/')) return img({ src: s, ...attrs })
  if (s.startsWith('&')) return img({ src: `/blob/${encodeURIComponent(s)}`, ...attrs })
  const mVideo = s.match(/\[video:[^\]]*\]\(\s*(&[^)\s]+\.sha256)\s*\)/)
  if (mVideo) return video({ controls: true, class: attrs.class || 'post-video', src: `/blob/${encodeURIComponent(mVideo[1])}` })
  const mAudio = s.match(/\[audio:[^\]]*\]\(\s*(&[^)\s]+\.sha256)\s*\)/)
  if (mAudio) return audio({ controls: true, class: attrs.class || 'post-audio', src: `/blob/${encodeURIComponent(mAudio[1])}` })
  const mImg = s.match(/!\[[^\]]*\]\(\s*(&[^)\s]+\.sha256)\s*\)/)
  if (mImg) return img({ src: `/blob/${encodeURIComponent(mImg[1])}`, ...attrs })
  return fallbackSrc ? img({ src: fallbackSrc, ...attrs }) : null
}

const toBlobUrl = (raw) => {
  if (!raw) return null
  const s = String(raw).trim()
  if (s.startsWith('&')) return `/blob/${encodeURIComponent(s)}`
  const m = s.match(/\((&[^)\s]+\.sha256)\s*\)/)
  return m ? `/blob/${encodeURIComponent(m[1])}` : null
}

const toImageUrl = (raw, fallback) => {
  if (!raw) return fallback
  const s = String(raw).trim()
  if (/^\[video:|^\[audio:/.test(s)) return fallback
  if (s.startsWith('/assets/') || s.startsWith('/blob/') || s.startsWith('/image/')) return s
  const url = toBlobUrl(raw)
  return url || fallback
}

const filterAndSortFeed = (feed, feedFilter) => {
  const parseDate = (d) => typeof d === 'string' ? Date.parse(d) : d;
  if (feedFilter === 'MINE') return feed.filter(m => m.author === userId);
  if (feedFilter === 'RECENT') {
    const last24h = Date.now() - MS_PER_DAY;
    return [...feed].filter(m => parseDate(m.createdAt) >= last24h).sort((a, b) => parseDate(b.createdAt) - parseDate(a.createdAt));
  }
  if (feedFilter === 'ALL') return [...feed].sort((a, b) => parseDate(b.createdAt) - parseDate(a.createdAt));
  if (feedFilter === 'TOP') return [...feed].sort((a, b) => (b.refeeds || 0) - (a.refeeds || 0));
  return feed;
};

const renderGallery = (sortedTribes) => {
  return div({ class: "gallery" },
    sortedTribes.length
      ? sortedTribes.map(t =>
          a({ href: `#tribe-${encodeURIComponent(t.id)}`, class: "gallery-item" },
           img({ src: toImageUrl(t.image, '/assets/images/default-tribe.png'), alt: t.title || "", class: "gallery-image" })
          )
        )
      : p(i18n.noTribes)
  );
};

const renderLightbox = (sortedTribes) => {
  return sortedTribes.map(t =>
    div(
      { id: `tribe-${encodeURIComponent(t.id)}`, class: "lightbox" },
      a({ href: "#", class: "lightbox-close" }, "×"),
      img({ src: toImageUrl(t.image, '/assets/images/default-tribe.png'), class: "lightbox-image", alt: t.title || "" })
    )
  );
};

exports.renderInvitePage = (inviteCode) => {
  const pageContent = div({ class: 'invite-page' },
    h2(i18n.tribeInviteCodeText.replace(/:\s*$/, '')),
    p(i18n.tribeInviteCodeHint || 'Share this code with someone you want to invite. They can join via /invites → Tribes.'),
    input({ type: 'text', value: inviteCode, readonly: 'readonly', class: 'tribe-invite-code-input' }),
    br(),
    form({ method: "GET", action: `/tribes` },
      button({ type: "submit", class: "filter-btn" }, i18n.walletBack)
    ),
  );
  return template(i18n.tribeInviteMode, section(pageContent));
};

exports.tribesView = async (tribes, filter, tribeId, query = {}, allTribes = null) => {
  const now = Date.now();
  const search = (query.search || '').toLowerCase();

  const allT0 = allTribes || tribes;
  const isAncestorPrivate = (t) => {
    let cur = t;
    const seen = new Set();
    while (cur && cur.parentTribeId && !seen.has(cur.parentTribeId)) {
      seen.add(cur.parentTribeId);
      const p = allT0.find(x => x.id === cur.parentTribeId);
      if (!p) break;
      if (p.isAnonymous) return true;
      cur = p;
    }
    return false;
  };
  const effectivePrivate = (t) => !!t.isAnonymous || isAncestorPrivate(t);
  const visible = (t) => !effectivePrivate(t) || t.author === userId || (Array.isArray(t.members) && t.members.includes(userId));
  const isMainTribe = (t) => !t.parentTribeId;
  const filtered = tribes.filter(t => {
    return (
      filter === 'all' ? visible(t) && isMainTribe(t) :
      filter === 'mine' ? t.author === userId :
      filter === 'membership' ? t.members.includes(userId) :
      filter === 'subtribes' ? visible(t) && !!t.parentTribeId :
      filter === 'recent' ? visible(t) && isMainTribe(t) && ((typeof t.createdAt === 'string' ? Date.parse(t.createdAt) : t.createdAt) >= now - MS_PER_DAY ) :
      filter === 'top' ? visible(t) && isMainTribe(t) :
      filter === 'gallery' ? visible(t) && isMainTribe(t) :
      filter === 'create' ? true :
      filter === 'edit' ? true :
      false
    );
  });

  const searched = filter === 'create' || filter === 'edit' || !search
    ? filtered
    : filtered.filter(t =>
        (t.title && t.title.toLowerCase().includes(search)) ||
        (t.description && t.description.toLowerCase().includes(search))
      );

  const sorted = filter === 'top'
    ? [...searched].sort((a, b) => b.members.length - a.members.length)
    : [...searched].sort((a, b) => {
        const ca = typeof a.createdAt === 'string' ? Date.parse(a.createdAt) : a.createdAt;
        const cb = typeof b.createdAt === 'string' ? Date.parse(b.createdAt) : b.createdAt;
        return cb - ca;
      });

  const title = i18n.tribesTitle;

  const header = div({ class: 'tags-header' }, h2(title), p(i18n.tribeDescription));

  const filters = div({ class: 'filters' },
    form({ method: 'GET', action: '/tribes', class: 'filter-box' },
      input({ type: 'hidden', name: 'filter', value: filter }),
      input({ type: 'text', name: 'search', placeholder: i18n.searchTribesPlaceholder, value: query.search || '', class: 'filter-box__input' }),
      div({ class: 'filter-box__controls' },
        button({ type: 'submit', class: 'filter-box__button' }, i18n.searchButton)
      )
    )
  );

  const modeButtons = div({ class: 'tribe-mode-buttons' },
    ['all','recent','mine','membership','subtribes','top','gallery'].map(f =>
    form({ method: 'GET', action: '/tribes' },
      input({ type: 'hidden', name: 'filter', value: f }),
      button({ type: 'submit', class: filter === f ? 'filter-btn active' : 'filter-btn' },
        i18n[`tribeFilter${f.charAt(0).toUpperCase()+f.slice(1)}`]
        )
      )
    ),
    form({ method: 'GET', action: '/tribes/create' },
      button({ type: 'submit', class: 'create-button' }, i18n.tribeCreateButton)
    )
  );

  const isEdit = filter === 'edit' && tribeId;
  const tribeToEdit = (isEdit ? tribes.find(t => t.id === tribeId) : null) || {};
  const isSubEdit = isEdit && !!tribeToEdit.parentTribeId;
  const createForm = (filter === 'create' || isEdit) ? div({ class: 'create-tribe-form' },
    h2(isEdit ? i18n.updateTribeTitle : i18n.createTribeTitle),
    form({
    method: 'POST',
    action: isEdit ? `/tribes/update/${encodeURIComponent(tribeToEdit.id)}` : '/tribes/create',
    enctype: 'multipart/form-data'
    },
    label({ for: 'title' }, i18n.tribeTitleLabel),
    br,
    input({ type: 'text', name: 'title', maxlength: '100', id: 'title', required: true, placeholder: i18n.tribeTitlePlaceholder, value: tribeToEdit.title || '' }),
    br(),
    label({ for: 'description' }, i18n.tribeDescriptionLabel),
    br,
    textarea({ name: 'description', id: 'description', required: true, rows: 4, cols: 50, placeholder: i18n.tribeDescriptionPlaceholder }, tribeToEdit.description || ''),
    br,
    label({ for: 'location' }, i18n.tribeLocationLabel),
    br,
    input({ type: 'text', name: 'location', id: 'location', placeholder: i18n.tribeLocationPlaceholder, value: tribeToEdit.location || '' }),
    br,
    label(i18n.mapLocationTitle || 'Map Location'),
    br,
    input({ type: 'text', name: 'mapUrl', placeholder: i18n.mapUrlPlaceholder || '/maps/MAP_ID', value: tribeToEdit.mapUrl || '' }),
    br,
    label({ for: 'image' }, i18n.tribeImageLabel),
    br,
    input({ type: 'file', name: 'image', id: 'image' }),
    br(), br(),
    label({ for: 'tags' }, i18n.tribeTagsLabel),
    br,
    input({ type: 'text', name: 'tags', id: 'tags', placeholder: i18n.tribeTagsPlaceholder, value: (tribeToEdit.tags || []).join(', ') }),
    br,
    isSubEdit ? null : label({ for: 'isAnonymous' }, i18n.tribeIsAnonymousLabel),
    isSubEdit ? null : br,
    isSubEdit ? null : select({ name: 'isAnonymous', id: 'isAnonymous' },
      option({ value: 'true', selected: tribeToEdit.isAnonymous === true ? 'selected' : undefined }, i18n.tribePrivate),
      option({ value: 'false', selected: tribeToEdit.isAnonymous === false ? 'selected' : undefined }, i18n.tribePublic)
    ),
    isSubEdit ? null : br(),
    isSubEdit ? null : br(),
    label({ for: 'inviteMode' }, i18n.tribeModeLabel),
    br,
    select({ name: 'inviteMode', id: 'inviteMode' },
      option({ value: 'strict', selected: tribeToEdit.inviteMode === 'strict' ? 'selected' : undefined }, i18n.tribeStrict),
      option({ value: 'open', selected: tribeToEdit.inviteMode === 'open' ? 'selected' : undefined }, i18n.tribeOpen)
    ),
    br(), br(),
    button({ type: 'submit' }, isEdit ? i18n.tribeUpdateButton : i18n.tribeCreateButton)
    )
  ) : null;

  const allT = allTribes || tribes;

  const tribeCards = sorted.map(t => {
    const isMember = t.members.includes(userId);
    const parentTribe = t.parentTribeId ? allT.find(p => p.id === t.parentTribeId) : null;

    const isOwn = String(t.author) === String(userId);
    return div({ class: 'trending-card tribes-card' + (isOwn ? ' own-content' : '') },
      div({ class: 'card-header activity-card-header' },
        span(),
        renderContentActions(t.id, `/tribe/${encodeURIComponent(t.id)}`, { author: t.author, reportTitle: t.title })
      ),
      div({ class: 'card-section tribes-card-body' },
        div({ class: 'tribe-card-image-wrapper' },
          a({ href: `/tribe/${encodeURIComponent(t.id)}` },
            renderMediaBlob(t.image, '/assets/images/default-tribe.png', { class: 'tribe-card-hero-image' })
          ),
          isMember
            ? form({ method: 'GET', action: `/tribe/${encodeURIComponent(t.id)}`, class: 'tribe-visit-btn-wrapper' },
                button({ type: 'submit', class: 'filter-btn' }, t.parentTribeId ? String(i18n.tribeviewSubTribeButton || 'VISIT SUB-TRIBE').toUpperCase() : String(i18n.tribeviewTribeButton || '').toUpperCase())
              )
            : null
        ),
        div({ class: 'tribe-card-body' },
          div({ class: 'shop-title-row' },
            h2({ class: 'tribe-card-title' }, a({ href: `/tribe/${encodeURIComponent(t.id)}` }, t.title))
          ),
          div({ class: 'card-chips-row' },
            t.isAnonymous ? renderPrivacyChip(true, i18n) : renderPrivacyChip(false, i18n),
            t.isAnonymous ? renderTribeEncryptedChip(i18n) : null,
            renderModeChip(t.inviteMode, i18n),
            renderLifespanChip(t.lifetime, i18n)
          ),
          t.description ? p({ class: 'tribe-card-description' }, ...renderUrl(t.description)) : null,
          renderMapLocationVisitLabel(t.mapUrl),
          (parentTribe || t.location) ? table({ class: 'tribe-info-table' },
            parentTribe ? tr(
              td({ class: 'tribe-info-label' }, i18n.tribeRootLabel || 'ROOT'),
              td({ class: 'tribe-info-value', colspan: '3' }, a({ href: `/tribe/${encodeURIComponent(parentTribe.id)}` }, parentTribe.title))
            ) : null,
            t.location ? tr(
              td({ class: 'tribe-info-label' }, i18n.tribeLocationLabel || 'LOCATION'),
              td({ class: 'tribe-info-value', colspan: '3' }, ...renderUrl(t.location))
            ) : null
          ) : null,
          div({ class: 'tribe-card-members' },
            span({ class: 'tribe-members-count' }, `${i18n.tribeMembersCount}: ${t.memberCount != null ? t.memberCount : t.members.length}`)
          ),
          (t.openInviteCode && !isMember && String(t.author) !== String(userId)) ? div({ class: 'tribe-card-join' },
            form({ method: 'POST', action: '/tribes/open-invite/join' },
              input({ type: 'hidden', name: 'tribeId', value: t.id }),
              button({ type: 'submit', class: 'tribe-action-btn' }, i18n.tribeJoinOpen)
            ),
            renderInviteQrCard({ qrDataUrl: t.openInviteQr, name: t.title })
          ) : null,
          isMember ? div({ class: 'tribe-card-actions' },
            !isLarpHouseTribe(t)
              ? form({ method: 'POST', action: '/tribes/generate-invite' },
                  input({ type: 'hidden', name: 'tribeId', value: t.id }),
                  button({ type: 'submit', class: 'tribe-action-btn' }, i18n.tribeGenerateInvite)
                )
              : null,
            form({ method: 'POST', action: `/tribes/leave/${encodeURIComponent(t.id)}` },
              button({ type: 'submit', class: 'tribe-action-btn danger-btn' }, i18n.tribeLeaveButton)
            )
          ) : null,
          filter === 'mine' ? div({ class: 'tribe-actions' },
            form({ method: 'GET', action: `/tribes/edit/${encodeURIComponent(t.id)}` }, button({ type: 'submit' }, i18n.tribeUpdateButton)),
            form({ method: 'POST', action: `/tribes/delete/${encodeURIComponent(t.id)}` }, button({ type: 'submit', class: 'danger-btn' }, i18n.tribeDeleteButton))
          ) : null
        )
      )
    );
  });

  return template(
    title,
    section(header),
    section(filters),
    section(modeButtons),
    section(
      (filter === 'create' || filter === 'edit')
        ? createForm
        : filter === 'gallery'
          ? renderGallery(sorted)
          : div({ class: 'tribe-grid' },
              tribeCards.length > 0 ? tribeCards : p(i18n.noTribes)
            )
     ),
    ...renderLightbox(sorted)
  );
};

const renderFeedTribeView = async (feedItems, tribe, query = {}, filter) => {
  const feed = Array.isArray(feedItems) ? feedItems : [];
  const feedFilter = (query.feedFilter || 'RECENT').toUpperCase();
  const filteredFeed = filterAndSortFeed(feed, feedFilter);
  return div({ class: 'tribe-feed-full' },
    div({ class: 'feed-actions' },
      ['TOP', 'MINE', 'ALL', 'RECENT'].map(f =>
	form({ method: 'GET', action: `/tribe/${encodeURIComponent(tribe.id)}` },
	  input({ type: 'hidden', name: 'section', value: 'feed' }),
	  input({ type: 'hidden', name: 'feedFilter', value: f }),
	  button({ type: 'submit', class: feedFilter === f ? 'filter-btn active' : 'filter-btn' }, String(i18n[`tribeFeedFilter${f}`]).toUpperCase())
	)
      )
    ),
    filteredFeed.length === 0
      ? p(i18n.tribeFeedEmpty)
      : div({ class: 'feed-list' },
          filteredFeed.map(m => div({ class: 'feed-item' },
            div({ class: 'feed-row' },
		div({ class: 'refeed-column' },
		  h1(`${m.refeeds || 0}`),
		  !(m.refeeds_inhabitants || []).includes(userId)
		    ? form(
			{ method: 'POST', action: `/tribe/${encodeURIComponent(tribe.id)}/refeed/${encodeURIComponent(m.id)}` },
			button({ class: 'refeed-btn' }, i18n.tribeFeedRefeed)
		      )
		    : null
		),
              div({ class: 'feed-main' },
                p(`${new Date(m.createdAt).toLocaleString()} — `, userLink(m.author)),
                br,
                p(...renderUrl(m.description))
              )
            )
          ))
        )
  );
};

const sectionLink = (tribe, sectionKey, label, currentSection) =>
  form({ method: 'GET', action: `/tribe/${encodeURIComponent(tribe.id)}` },
    input({ type: 'hidden', name: 'section', value: sectionKey }),
    button({ type: 'submit', class: currentSection === sectionKey ? 'filter-btn active' : 'filter-btn' }, label)
  );

const renderSectionNav = (tribe, section) => {
  const firstGroup = [{ key: 'activity', label: i18n.tribeSectionActivity }, { key: 'inhabitants', label: i18n.tribeSectionInhabitants }];
  if (!tribe.parentTribeId) firstGroup.push({ key: 'subtribes', label: i18n.tribeSubTribes });
  if (!tribe.parentTribeId) firstGroup.push({ key: 'governance', label: i18n.tribeSectionGovernance || 'GOVERNANCE' });
  const sections = [
    { items: firstGroup },
    { items: [{ key: 'votations', label: i18n.tribeSectionVotations }, { key: 'polls', label: i18n.pollsTitle }, { key: 'events', label: i18n.tribeSectionEvents }, { key: 'tasks', label: i18n.tribeSectionTasks }] },
    { items: [{ key: 'feed', label: i18n.tribeSectionFeed }, { key: 'forum', label: i18n.tribeSectionForum }, { key: 'maps', label: i18n.tribeSectionMaps || 'MAPS' }, { key: 'torrents', label: i18n.tribeSectionTorrents || 'TORRENTS' }, { key: 'pads', label: i18n.tribeSectionPads || 'PADS' }, { key: 'chats', label: i18n.tribeSectionChats || 'CHATS' }, { key: 'calendars', label: i18n.tribeSectionCalendars || 'CALENDARS' }] },
    { items: [{ key: 'images', label: i18n.tribeSectionImages || 'IMAGES' }, { key: 'audios', label: i18n.tribeSectionAudios || 'AUDIOS' }, { key: 'videos', label: i18n.tribeSectionVideos || 'VIDEOS' }, { key: 'documents', label: i18n.tribeSectionDocuments || 'DOCUMENTS' }, { key: 'bookmarks', label: i18n.tribeSectionBookmarks || 'BOOKMARKS' }] },
    { items: [{ key: 'tags', label: i18n.tribeSectionTags || 'TAGS' }, { key: 'search', label: i18n.tribeSectionSearch }] },
  ];
  return div({ class: 'tribe-section-nav no-border' },
    sections.map(g =>
      div({ class: 'tribe-section-group no-border' },
        g.items.map(s => s.href
          ? form({ method: 'GET', action: s.href },
              button({ type: 'submit', class: 'filter-btn' }, s.label)
            )
          : sectionLink(tribe, s.key, s.label, section))
      )
    )
  );
};

const statusI18n = () => ({
  'OPEN': i18n.tribeStatusOpen,
  'CLOSED': i18n.tribeStatusClosed,
  'IN-PROGRESS': i18n.tribeStatusInProgress,
});

const priorityI18n = () => ({
  'LOW': i18n.tribePriorityLow,
  'MEDIUM': i18n.tribePriorityMedium,
  'HIGH': i18n.tribePriorityHigh,
  'CRITICAL': i18n.tribePriorityCritical,
});

const inviteModeI18n = () => ({
  'strict': i18n.tribeStrict,
  'open': i18n.tribeOpen,
});

const forumCatI18n = () => ({
  'GENERAL': i18n.tribeForumCatGeneral,
  'PROPOSAL': i18n.tribeForumCatProposal,
  'QUESTION': i18n.tribeForumCatQuestion,
  'ANNOUNCEMENT': i18n.tribeForumCatAnnouncement,
});

const mediaTypeI18n = () => ({
  'all': i18n.tribeMediaFilterAll,
  'image': i18n.tribeMediaTypeImage,
  'video': i18n.tribeMediaTypeVideo,
  'audio': i18n.tribeMediaTypeAudio,
  'document': i18n.tribeMediaTypeDocument,
  'bookmark': i18n.tribeMediaTypeBookmark,
});

const taskFilterI18n = () => ({
  'all': i18n.tribeTaskFilterAll,
  'open': i18n.tribeStatusOpen,
  'in-progress': i18n.tribeStatusInProgress,
  'closed': i18n.tribeStatusClosed,
});

const statusBadge = (status) => {
  const cls = status === 'OPEN' ? 'tribe-content-status-open'
    : status === 'CLOSED' ? 'tribe-content-status-closed'
    : 'tribe-content-status-in-progress';
  return span({ class: `tribe-content-status ${cls}` }, statusI18n()[status] || status);
};

const priorityLabel = (priority) => {
  const cls = `tribe-priority-${(priority || 'low').toLowerCase()}`;
  return span({ class: cls }, priorityI18n()[priority] || (priority || '').toUpperCase());
};

const contentTypeVerb = (ct) => {
  const map = { event: i18n.tribeActivityCreated, task: i18n.tribeActivityCreated, votation: i18n.tribeActivityCreated, forum: i18n.tribeActivityPosted, 'forum-reply': i18n.tribeActivityReplied, media: i18n.tribeActivityCreated, feed: i18n.tribeActivityPosted };
  return map[ct] || i18n.tribeActivityCreated;
};

const contentTypeName = (ct) => {
  const map = { event: i18n.tribeSectionEvents, task: i18n.tribeSectionTasks, votation: i18n.tribeSectionVotations, poll: i18n.pollsTitle, forum: i18n.tribeSectionForum, 'forum-reply': i18n.tribeSectionForum, media: i18n.tribeSectionMedia, feed: i18n.tribeSectionFeed, pad: i18n.tribeSectionPads || 'PADS', chat: i18n.tribeSectionChats || 'CHATS', calendar: i18n.tribeSectionCalendars || 'CALENDARS', map: i18n.tribeSectionMaps || 'MAPS' };
  return map[ct] || ct;
};

const activitySectionMap = {
  event: 'events', task: 'tasks', votation: 'votations', poll: 'polls',
  forum: 'forum', 'forum-reply': 'forum',
  feed: 'feed',
  pad: 'pads', chat: 'chats', calendar: 'calendars', map: 'maps', torrent: 'torrents'
};

const activitySectionForItem = (item) => {
  if (item.contentType === 'media' && item.mediaType) {
    const map = { image: 'images', audio: 'audios', video: 'videos', document: 'documents', bookmark: 'bookmarks', torrent: 'torrents' };
    return map[item.mediaType] || 'media';
  }
  return activitySectionMap[item.contentType] || 'activity';
};

const activityMediaTypeName = (mt) => {
  const map = { image: i18n.tribeSectionImages, audio: i18n.tribeSectionAudios, video: i18n.tribeSectionVideos, document: i18n.tribeSectionDocuments, bookmark: i18n.tribeSectionBookmarks, torrent: i18n.tribeSectionTorrents };
  return map[mt] || i18n.tribeSectionMedia || 'MEDIA';
};

const renderTribeActivitySection = (tribe, sectionData) => {
  const { activities } = sectionData || { activities: [] };
  if (activities.length === 0) return div({ class: 'tribe-content-list' }, p(i18n.tribeActivityEmpty));
  const tribeUrl = `/tribe/${encodeURIComponent(tribe.id)}`;
  return div({ class: 'tribe-content-list tribe-content-list-spaced' },
    activities.slice(0, 50).map(item => {
      if (item.encrypted) return div({ class: 'card card-rpg' }, div({ class: 'tribe-card-body' }, p({ class: 'tribe-meta-label' }, i18n.tribeContentEncrypted || 'Encrypted content')));
      if (item.contentType === 'chatThread') {
        const replies = Array.isArray(item.replies) ? item.replies : [];
        const tDate = item.timestamp ? new Date(item.timestamp).toLocaleString() : '';
        const headerText = item.tribeName
          ? `[${String(i18n.typeChat || 'CHAT').toUpperCase()} · THREAD · ${item.tribeName}]`
          : `[${String(i18n.typeChat || 'CHAT').toUpperCase()} · THREAD]`;
        return div({ class: 'card card-rpg tribe-card-padded chat-thread' },
          div({ class: 'card-header' },
            h2({ class: 'card-label' }, headerText),
            a({ href: item.directUrl, class: 'filter-btn' }, i18n.viewDetails || 'View Details')
          ),
          div({ class: 'tribe-card-body' },
            item.title ? div({ class: 'card-field' }, span({ class: 'card-value' }, item.title)) : null,
            item.description ? p(String(item.description).substring(0, 200)) : null,
            replies.map(r => div({ class: 'thread-reply-item' },
              r.text ? p({ class: 'post-text post-text-pre' }, String(r.text)) : null,
              div({ class: 'card-footer thread-reply-footer' },
                span({ class: 'date-link' }, r.createdAt ? new Date(r.createdAt).toLocaleString() : ''),
                userLink(r.author, '')
              )
            ))
          ),
          p({ class: 'card-footer' },
            span({ class: 'date-link' }, `${tDate} ${i18n.performed || ''} `),
            userLink(item.author, item.authorName)
          )
        );
      }
      const date = item.timestamp ? new Date(item.timestamp).toLocaleString() : '';
      const typeLabel = item.contentType === 'media' && item.mediaType
        ? activityMediaTypeName(item.mediaType)
        : contentTypeName(item.contentType);
      const headerText = item.tribeName
        ? `[${String(typeLabel).toUpperCase()} · ${item.tribeName}]`
        : `[${String(typeLabel).toUpperCase()}]`;
      const targetSection = activitySectionForItem(item);
      const blobUrl = item.contentType === 'media' ? toBlobUrl(item.image) : null;
      const mediaContent =
        item.contentType === 'media' && item.mediaType === 'image' && blobUrl
          ? a({ href: blobUrl, target: '_blank' }, img({ src: blobUrl, alt: item.title || '', class: 'tribe-media-thumb' }))
        : item.contentType === 'media' && item.mediaType === 'audio' && blobUrl
          ? audio({ src: blobUrl, controls: true, class: 'tribe-media-audio' })
        : item.contentType === 'media' && item.mediaType === 'video' && blobUrl
          ? video({ src: blobUrl, controls: true, class: 'tribe-media-thumb' })
        : item.contentType === 'media' && item.mediaType === 'document' && blobUrl
          ? a({ href: blobUrl, target: '_blank', class: 'tribe-action-btn' }, i18n.readDocument || 'Read Document')
        : item.contentType === 'media' && item.mediaType === 'bookmark' && (item.url || item.description)
          ? a({ href: item.url || item.description, target: '_blank', class: 'tribe-action-btn' }, item.url || item.description)
        : null;
      return div({ class: 'card card-rpg tribe-card-padded' },
        div({ class: 'card-header' },
          h2({ class: 'card-label' }, headerText),
          item.directUrl
            ? a({ href: item.directUrl, class: 'filter-btn' }, i18n.viewDetails || 'View Details')
            : form({ method: 'GET', action: tribeUrl },
                input({ type: 'hidden', name: 'section', value: targetSection }),
                button({ type: 'submit', class: 'filter-btn' }, i18n.viewDetails || 'View Details')
              )
        ),
        div({ class: 'tribe-card-body' },
          item.title ? div({ class: 'card-field' },
            span({ class: 'card-value' }, item.title)
          ) : null,
          mediaContent,
          item.description && !(item.contentType === 'media' && item.mediaType === 'bookmark' && item.description === item.url) ? p(item.description.substring(0, 200)) : null
        ),
        p({ class: 'card-footer' },
          span({ class: 'date-link' }, `${date} ${i18n.performed || ''} `),
          userLink(item.author, item.authorName)
        )
      );
    })
  );
};

const engagementScore = (item) => (item.refeeds || 0) + (Array.isArray(item.attendees) ? item.attendees.length : 0) + Object.values(item.votes || {}).reduce((s, arr) => s + (Array.isArray(arr) ? arr.length : 0), 0) + (Array.isArray(item.assignees) ? item.assignees.length : 0) + (Array.isArray(item.opinions_inhabitants) ? item.opinions_inhabitants.length : 0);

const renderTribeTrendingSection = (tribe, sectionData, query) => {
  const { items, period } = sectionData || { items: [], period: 'all' };
  const tribeUrl = `/tribe/${encodeURIComponent(tribe.id)}`;
  const periodBtn = (key, label) => form({ method: 'GET', action: tribeUrl }, input({ type: 'hidden', name: 'section', value: 'trending' }), input({ type: 'hidden', name: 'period', value: key }), button({ type: 'submit', class: period === key ? 'filter-btn active' : 'filter-btn' }, label));
  return div({ class: 'tribe-content-list' },
    div({ class: 'tribe-content-header' }, h2(i18n.tribeSectionTrending)),
    div({ class: 'tribe-filter-bar' }, periodBtn('day', i18n.tribeTrendingPeriodDay), periodBtn('week', i18n.tribeTrendingPeriodWeek), periodBtn('all', i18n.tribeTrendingPeriodAll)),
    items.length === 0 ? p(i18n.tribeTrendingEmpty) :
      items.slice(0, 30).map((item, idx) => {
        if (item.encrypted) return div({ class: 'tribe-content-card' }, div({ class: 'tribe-content-meta' }, span(`#${idx + 1}`)), p({ class: 'tribe-meta-label' }, i18n.tribeContentEncrypted || 'Encrypted content'));
        return div({ class: 'tribe-content-card' },
        div({ class: 'tribe-content-meta' },
          span(`#${idx + 1}`),
          span({ class: 'tribe-badge' }, contentTypeName(item.contentType)),
          span(`${i18n.tribeTrendingEngagement}: ${engagementScore(item)}`),
          (() => { const entries = Object.entries(item.opinions || {}); if (!entries.length) return null; const top = entries.reduce((a, b) => b[1] > a[1] ? b : a); return span(`| ${i18n.tribeTopCategory}: ${i18n['opinionCat' + top[0].charAt(0).toUpperCase() + top[0].slice(1)] || top[0]}`); })()
        ),
        item.title ? h2(item.title) : item.description ? h2(item.description) : null,
        div({ class: 'tribe-content-meta' },
          item.refeeds ? span(`${i18n.tribeActivityRefeed}: ${item.refeeds}`) : null,
          Array.isArray(item.attendees) && item.attendees.length ? span(`${i18n.tribeEventAttendees}: ${item.attendees.length}`) : null
        ),
        p({ class: 'tribe-meta-label' }, userLink(item.author))
      ); })
  );
};

const renderTribeTagsSection = (tribe, sectionData, query) => {
  const tagsList = Array.isArray(sectionData?.tags) ? sectionData.tags : [];
  const selectedTag = sectionData?.selectedTag || '';
  const filteredItems = Array.isArray(sectionData?.filteredItems) ? sectionData.filteredItems : [];
  const tribeUrl = `/tribe/${encodeURIComponent(tribe.id)}`;
  const sortedTags = tagsList.slice().sort((a, b) => b.count - a.count || a.tag.localeCompare(b.tag));
  return section(
    div({ class: 'tags-header' },
      h2(i18n.tribeSectionTags || i18n.tagsTitle || 'TAGS'),
      p(i18n.tagsDescription || '')
    ),
    div({ class: 'tags-list' },
      tagsList.length === 0
        ? p(i18n.tagsNoItems || i18n.tribeTagsEmpty || 'No tags yet')
        : table({ class: 'tag-table' },
            thead(tr(
              th(i18n.tagsTableHeaderTag || 'Tag'),
              th(i18n.tagsTableHeaderCount || 'Count')
            )),
            tbody(
              sortedTags.map(t => tr(
                td(a({ href: `${tribeUrl}?section=tags&tag=${encodeURIComponent(t.tag)}` }, t.tag)),
                td(`${t.count}`)
              ))
            )
          )
    ),
    selectedTag ? div({ class: 'tribe-content-list' },
      h2(`#${selectedTag} (${filteredItems.length})`),
      filteredItems.length === 0 ? p(i18n.tribeTagsEmpty || 'No items') :
        filteredItems.slice(0, 50).map(item => div({ class: 'card card-rpg' },
          div({ class: 'card-header' }, h2({ class: 'card-label' }, `[${String(contentTypeName(item.contentType)).toUpperCase()}]`)),
          div({ class: 'card-body' },
            item.title ? div({ class: 'card-field' }, span({ class: 'card-value' }, item.title)) : null,
            item.description ? p(item.description.substring(0, 200)) : null
          ),
          p({ class: 'card-footer' },
            span({ class: 'date-link' }, new Date(item.createdAt).toLocaleString()),
            userLink(item.author)
          )
        ))
    ) : null
  );
};

const renderTribeSearchSection = (tribe, sectionData, query) => {
  const { results } = sectionData || { results: [] };
  const sq = sectionData?.query || '';
  const tribeUrl = `/tribe/${encodeURIComponent(tribe.id)}`;
  return div({ class: 'tribe-content-list' },
    div({ class: 'tribe-content-header' }, h2(i18n.tribeSectionSearch)),
    form({ method: 'GET', action: tribeUrl, class: 'tribe-search-form' },
      input({ type: 'hidden', name: 'section', value: 'search' }),
      input({ type: 'text', name: 'q', value: sq, placeholder: i18n.tribeSearchPlaceholder, minlength: 2 }),
      button({ type: 'submit', class: 'create-button' }, i18n.tribeSectionSearch)
    ),
    sq.length > 0 && sq.length < 2 ? p(i18n.tribeSearchMinChars) : null,
    sq.length >= 2 ? div(
      h2(`${i18n.tribeSearchResults}: ${results.length}`),
      results.length === 0 ? p(i18n.tribeSearchEmpty) :
        results.map(item => div({ class: 'card card-rpg' },
          div({ class: 'card-header' },
            h2({ class: 'card-label' }, `[${String(contentTypeName(item.contentType)).toUpperCase()}]`)
          ),
          div({ class: 'card-body' },
            item.title ? div({ class: 'card-field' },
              span({ class: 'card-label' }, (i18n.title || 'Title') + ':'),
              span({ class: 'card-value' }, item.title)
            ) : null,
            item.description ? p(item.description.substring(0, 200)) : null
          ),
          p({ class: 'card-footer' },
            span({ class: 'date-link' }, new Date(item.createdAt).toLocaleDateString()),
            userLink(item.author)
          )
        ))
    ) : null
  );
};

const renderOverviewSection = (tribe, query, sectionData) => {
  const feed = Array.isArray(sectionData?.feed) ? sectionData.feed : [];
  const recentFeed = [...feed]
    .sort((a, b) => (Date.parse(b.createdAt) || b._ts || 0) - (Date.parse(a.createdAt) || a._ts || 0))
    .slice(0, 5);
  const events = Array.isArray(sectionData?.events) ? sectionData.events.slice(0, 3) : [];
  const tasks = Array.isArray(sectionData?.tasks) ? sectionData.tasks.slice(0, 3) : [];

  return div({ class: 'tribe-overview-grid' },
    div({ class: 'tribe-overview-section' },
      h2(i18n.tribeSectionFeed),
      recentFeed.length === 0 ? p(i18n.tribeFeedEmpty) :
        recentFeed.map(m =>
          div({ class: 'feed-item' },
            p(`${new Date(m.createdAt).toLocaleString()} — `, userLink(m.author)),
            p(...renderUrl(m.description))
          )
        )
    ),
    div({ class: 'tribe-overview-section' },
      h2(i18n.tribeSectionEvents),
      events.length === 0 ? p(i18n.tribeEventsEmpty) :
        events.map(e =>
          div({ class: 'tribe-content-card' },
            h2(e.title),
            div({ class: 'tribe-content-meta' },
              e.date ? span(e.date) : null,
              e.location ? span(e.location) : null,
              statusBadge(e.status)
            )
          )
        )
    ),
    div({ class: 'tribe-overview-section' },
      h2(i18n.tribeSectionTasks),
      tasks.length === 0 ? p(i18n.tribeTasksEmpty) :
        tasks.map(t =>
          div({ class: 'tribe-content-card' },
            h2(t.title),
            div({ class: 'tribe-content-meta' },
              priorityLabel(t.priority),
              statusBadge(t.status)
            )
          )
        )
    ),
    div({ class: 'tribe-overview-section' },
      h2(i18n.tribeSectionInhabitants),
      p(`${i18n.tribeMembersCount}: ${tribe.members.length}`),
      tribe.members.slice(0, 6).map(m =>
        userLink(m),
      )
    )
  );
};

const renderInhabitantsSection = (tribe, members) => {
  const resolved = Array.isArray(members) ? members : [];
  if (resolved.length === 0) return p(i18n.tribeInhabitantsEmpty);
  return div({ class: 'tribe-thumb-grid' },
    resolved.map(m =>
      a({ href: `/author/${encodeURIComponent(m.id)}`, class: 'tribe-thumb-link', title: m.name || m.id },
        img({ src: resolvePhoto(m.photo), class: 'tribe-thumb-img', alt: m.name || m.id })
      )
    )
  );
};

const createButtonI18n = {
  events: () => i18n.tribeEventCreate || 'Create Event',
  tasks: () => i18n.tribeTaskCreate || 'Create Task',
  votations: () => i18n.tribeVotationCreate || 'Create Votation',
  forum: () => i18n.tribeForumCreate || 'Create Forum',
  subtribes: () => i18n.tribeSubTribesCreate || 'Create Sub-Tribe',
};

const renderCreateForm = (tribe, contentType, fields) => {
  const tribeUrl = `/tribe/${encodeURIComponent(tribe.id)}`;
  const hasFile = fields.some(f => f.type === 'file');
  const formAttrs = { method: 'POST', action: `${tribeUrl}/${contentType}/create` };
  if (hasFile) formAttrs.enctype = 'multipart/form-data';
  const btnLabel = createButtonI18n[contentType] ? createButtonI18n[contentType]() : i18n.tribeCreateButton;
  return div({ class: 'create-tribe-form' },
    form(formAttrs,
      ...fields.map(f => {
        const prefix = f.spaceBefore ? [br()] : [];
        if (f.type === 'textarea') return [...prefix, label({ for: f.name }, f.label), br, textarea({ name: f.name, id: f.name, rows: f.rows || 4, required: f.required, placeholder: f.placeholder }, ''), br()];
        if (f.type === 'select') return [...prefix, label({ for: f.name }, f.label), br, select({ name: f.name, id: f.name }, ...f.options.map(o => option({ value: o.value }, o.label))), br()];
        if (f.type === 'file') return [...prefix, label({ for: f.name }, f.label), br, input({ type: 'file', name: f.name, id: f.name, accept: f.accept || '*/*' }), br()];
        const attrs = { type: f.type || 'text', name: f.name, id: f.name, required: f.required, placeholder: f.placeholder };
        if (f.min) attrs.min = f.min;
        return [...prefix, br, label({ for: f.name }, f.label), br, input(attrs), br()];
      }).flat(),br(),
      button({ type: 'submit', class: 'create-button' }, btnLabel)
    )
  );
};

const renderEventsSection = (tribe, items, query) => {
  const events = Array.isArray(items) ? items : [];
  const action = query.action;
  const today = new Date().toISOString().split('T')[0];
  if (action === 'create') {
    return renderCreateForm(tribe, 'events', [
      { name: 'title', label: i18n.tribeEventTitle, required: true, placeholder: i18n.tribeEventTitle },
      { name: 'description', type: 'textarea', label: i18n.tribeEventDescription, required: true, placeholder: i18n.tribeEventDescription },
      { name: 'date', type: 'date', label: i18n.tribeEventDate, required: true, min: today },
      { name: 'location', label: i18n.tribeEventLocation, placeholder: i18n.tribeEventLocation },
    ]);
  }
  const tribeUrl = `/tribe/${encodeURIComponent(tribe.id)}`;
  return div({ class: 'tribe-content-list' },
    div({ class: 'tribe-content-header' },
      h2(i18n.tribeSectionEvents),
      form({ method: 'GET', action: tribeUrl },
        input({ type: 'hidden', name: 'section', value: 'events' }),
        input({ type: 'hidden', name: 'action', value: 'create' }),
        button({ type: 'submit', class: 'create-button' }, i18n.tribeEventCreate)
      )
    ),
    events.length === 0 ? p(i18n.tribeEventsEmpty) :
      events.map(e => div({ class: 'tribe-content-card' },
        h2(e.title),
        e.description ? p(...renderUrl(e.description)) : null,
        e.date ? div({ class: 'card-field' },
          span({ class: 'card-label' }, (i18n.tribeEventDate || 'Date') + ':'),
          span({ class: 'card-value' }, e.date)
        ) : null,
        e.location ? div({ class: 'card-field' },
          span({ class: 'card-label' }, (i18n.tribeEventLocation || 'Location') + ':'),
          span({ class: 'card-value' }, ...renderUrl(e.location))
        ) : null,
        div({ class: 'card-field' },
          span({ class: 'card-label' }, (i18n.tribeEventAttendees || 'Attendees') + ':'),
          span({ class: 'card-value' }, String((e.attendees || []).length))
        ),
        statusBadge(e.status),
        div({ class: 'tribe-content-actions' },
          form({ method: 'POST', action: `${tribeUrl}/events/attend/${encodeURIComponent(e.id)}` },
            button({ type: 'submit', class: 'filter-btn' },
              (e.attendees || []).includes(userId) ? i18n.tribeEventUnattend : i18n.tribeEventAttend
            )
          ),
          e.author === userId ? form({ method: 'POST', action: `${tribeUrl}/content/delete/${encodeURIComponent(e.id)}` },
            button({ type: 'submit', class: 'filter-btn danger-btn' }, i18n.tribeContentDelete)
          ) : null
        )
      ))
  );
};

const renderTasksSection = (tribe, items, query) => {
  const tasks = Array.isArray(items) ? items : [];
  const action = query.action;
  const today = new Date().toISOString().split('T')[0];
  if (action === 'create') {
    return renderCreateForm(tribe, 'tasks', [
      { name: 'title', label: i18n.tribeTaskTitle, required: true, placeholder: i18n.tribeTaskTitle },
      { name: 'description', type: 'textarea', label: i18n.tribeTaskDescription, required: true, placeholder: i18n.tribeTaskDescription },
      { name: 'priority', type: 'select', label: i18n.tribeTaskPriority, options: [
        { value: 'LOW', label: i18n.tribePriorityLow }, { value: 'MEDIUM', label: i18n.tribePriorityMedium },
        { value: 'HIGH', label: i18n.tribePriorityHigh }, { value: 'CRITICAL', label: i18n.tribePriorityCritical }
      ]},
      { name: 'deadline', type: 'date', label: i18n.tribeTaskDeadline, min: today },
    ]);
  }
  const tribeUrl = `/tribe/${encodeURIComponent(tribe.id)}`;
  return div({ class: 'tribe-content-list' },
    div({ class: 'tribe-content-header' },
      h2(i18n.tribeSectionTasks),
      form({ method: 'GET', action: tribeUrl },
        input({ type: 'hidden', name: 'section', value: 'tasks' }),
        input({ type: 'hidden', name: 'action', value: 'create' }),
        button({ type: 'submit', class: 'create-button' }, i18n.tribeTaskCreate)
      )
    ),
    tasks.length === 0 ? p(i18n.tribeTasksEmpty) :
      tasks.map(t => div({ class: 'tribe-content-card' },
        h2(t.title),
        t.description ? p(...renderUrl(t.description)) : null,
        div({ class: 'card-field' },
          span({ class: 'card-label' }, (i18n.tribeTaskPriority || 'Priority') + ':'),
          priorityLabel(t.priority)
        ),
        div({ class: 'card-field' },
          span({ class: 'card-label' }, (i18n.tribeStatusLabel || 'Status') + ':'),
          statusBadge(t.status)
        ),
        div({ class: 'card-field' },
          span({ class: 'card-label' }, (i18n.tribeTaskAssignees || 'Assignees') + ':'),
          span({ class: 'card-value' }, String((t.assignees || []).length))
        ),
        br(),
        t.deadline ? div({ class: 'card-field' },
          span({ class: 'card-label' }, (i18n.tribeTaskDeadline || 'Deadline') + ':'),
          span({ class: 'card-value' }, t.deadline)
        ) : null,
        div({ class: 'tribe-content-actions' },
          form({ method: 'POST', action: `${tribeUrl}/tasks/assign/${encodeURIComponent(t.id)}` },
            button({ type: 'submit', class: 'filter-btn' },
              (t.assignees || []).includes(userId) ? i18n.tribeTaskUnassign : i18n.tribeTaskAssign
            )
          ),
          t.status !== 'IN-PROGRESS' && t.author === userId ? form({ method: 'POST', action: `${tribeUrl}/tasks/status/${encodeURIComponent(t.id)}` },
            input({ type: 'hidden', name: 'status', value: 'IN-PROGRESS' }),
            button({ type: 'submit', class: 'filter-btn' }, i18n.tribeTaskStatusInProgress)
          ) : null,
          t.status !== 'CLOSED' && t.author === userId ? form({ method: 'POST', action: `${tribeUrl}/tasks/status/${encodeURIComponent(t.id)}` },
            input({ type: 'hidden', name: 'status', value: 'CLOSED' }),
            button({ type: 'submit', class: 'filter-btn' }, i18n.tribeTaskStatusClosed)
          ) : null,
          t.author === userId ? form({ method: 'POST', action: `${tribeUrl}/content/delete/${encodeURIComponent(t.id)}` },
            button({ type: 'submit', class: 'filter-btn danger-btn' }, i18n.tribeContentDelete)
          ) : null
        )
      ))
  );
};

const renderTribePollsSection = (tribe, items, query) => {
  const polls = Array.isArray(items) ? items : [];
  const tribeUrl = `/tribe/${encodeURIComponent(tribe.id)}`;
  if (query.action === 'create') {
    return div({ class: 'create-tribe-form' },
      form({ method: 'POST', action: `${tribeUrl}/polls/create` },
        label(i18n.pollQuestion), br,
        input({ type: 'text', name: 'question', required: true, maxlength: '300', placeholder: i18n.pollQuestionPlaceholder }), br(),
        label(i18n.pollOptions), br,
        textarea({ name: 'options', rows: 5, required: true, placeholder: i18n.pollOptionsPlaceholder }, ''), br(),
        div({ class: 'poll-switch' },
          input({ type: 'hidden', name: 'anonymous', value: '0' }),
          label(input({ type: 'checkbox', name: 'anonymous', value: '1' }), ' ', i18n.pollAnonymousLabel)
        ),
        div({ class: 'poll-switch' },
          input({ type: 'hidden', name: 'multiple', value: '0' }),
          label(input({ type: 'checkbox', name: 'multiple', value: '1' }), ' ', i18n.pollMultipleLabel)
        ),
        button({ type: 'submit', class: 'create-button' }, i18n.pollPublishButton)
      )
    );
  }
  const returnTo = `${tribeUrl}?section=polls`;
  return div({ class: 'tribe-content-list' },
    div({ class: 'tribe-content-header' },
      h2(i18n.pollsTitle),
      form({ method: 'GET', action: tribeUrl },
        input({ type: 'hidden', name: 'section', value: 'polls' }),
        input({ type: 'hidden', name: 'action', value: 'create' }),
        button({ type: 'submit', class: 'create-button' }, i18n.pollCreateButton)
      )
    ),
    polls.length === 0 ? p(i18n.pollsNoItems) :
      polls.map(poll => div({ class: 'tribe-content-card poll-card' },
        h2(poll.undecryptable ? i18n.contentAccessDenied : poll.question),
        poll.undecryptable ? null : div({ class: 'card-chips-row' },
          statusBadge(poll.status),
          poll.anonymous ? span({ class: 'chat-poll-tag' }, i18n.pollAnonymous) : null,
          poll.multiple ? span({ class: 'chat-poll-tag' }, i18n.pollMultiple) : null
        ),
        poll.undecryptable ? null : (poll.hasVoted || poll.status === 'CLOSED' ? renderPollResults(poll) : null),
        poll.undecryptable ? null : renderPollBallot(poll, returnTo, '/polls'),
        poll.undecryptable ? null : div({ class: 'card-field' },
          span({ class: 'card-label' }, `${i18n.pollVoters}: `),
          span({ class: 'card-value' }, String(poll.totalVoters))
        ),
        div({ class: 'card-field' },
          span({ class: 'card-label' }, i18n.createdBy + ': '),
          userLink(poll.author)
        ),
        poll.author === userId && poll.status === 'OPEN'
          ? form({ method: 'POST', action: `/polls/close/${encodeURIComponent(poll.id)}` },
              input({ type: 'hidden', name: 'returnTo', value: returnTo }),
              button({ type: 'submit', class: 'filter-btn' }, i18n.pollCloseButton)
            )
          : null,
        poll.author === userId
          ? form({ method: 'POST', action: `/polls/delete/${encodeURIComponent(poll.id)}` },
              input({ type: 'hidden', name: 'returnTo', value: returnTo }),
              button({ type: 'submit', class: 'filter-btn danger-btn' }, i18n.pollDeleteButton)
            )
          : null
      ))
  );
};

const renderVotationsSection = (tribe, items, query) => {
  const votations = Array.isArray(items) ? items : [];
  const action = query.action;
  const today = new Date().toISOString().split('T')[0];
  if (action === 'create') {
    return div({ class: 'create-tribe-form' },
      form({ method: 'POST', action: `/tribe/${encodeURIComponent(tribe.id)}/votations/create` },
        label({ for: 'title' }, i18n.tribeVotationTitle), br,
        input({ type: 'text', name: 'title', maxlength: '100', id: 'title', required: true, placeholder: i18n.tribeVotationTitle }), br(),
        label({ for: 'description' }, i18n.tribeVotationDescription), br,
        textarea({ name: 'description', id: 'description', rows: 3, placeholder: i18n.tribeVotationDescription }, ''), br(),
        label({ for: 'deadline' }, i18n.tribeVotationDeadline), br,
        input({ type: 'date', name: 'deadline', id: 'deadline', min: today }), br(),
        br(),
        label(i18n.tribeVotationOptions), br,
        input({ type: 'text', name: 'option1', placeholder: `${i18n.tribeVotationOptionPlaceholder} 1`, required: true }), br(),
        input({ type: 'text', name: 'option2', placeholder: `${i18n.tribeVotationOptionPlaceholder} 2`, required: true }), br(),
        input({ type: 'text', name: 'option3', placeholder: `${i18n.tribeVotationOptionPlaceholder} 3` }), br(),
        input({ type: 'text', name: 'option4', placeholder: `${i18n.tribeVotationOptionPlaceholder} 4` }), br(),
        button({ type: 'submit', class: 'create-button' }, i18n.tribeVotationCreate)
      )
    );
  }
  const tribeUrl = `/tribe/${encodeURIComponent(tribe.id)}`;
  return div({ class: 'tribe-content-list' },
    div({ class: 'tribe-content-header' },
      h2(i18n.tribeSectionVotations),
      form({ method: 'GET', action: tribeUrl },
        input({ type: 'hidden', name: 'section', value: 'votations' }),
        input({ type: 'hidden', name: 'action', value: 'create' }),
        button({ type: 'submit', class: 'create-button' }, i18n.tribeVotationCreate)
      )
    ),
    votations.length === 0 ? p(i18n.tribeVotationsEmpty) :
      votations.map(v => {
        const opts = Array.isArray(v.options) ? v.options : [];
        const votes = v.votes || {};
        const totalVotes = Object.values(votes).reduce((sum, arr) => sum + (Array.isArray(arr) ? arr.length : 0), 0);
        const hasVoted = Object.values(votes).some(arr => Array.isArray(arr) && arr.includes(userId));
        const isOpen = v.status === 'OPEN';

        return div({ class: 'tribe-content-card' },
          h2(v.title),
          v.description ? p(...renderUrl(v.description)) : null,
          statusBadge(v.status),
          v.deadline ? div({ class: 'card-field' },
            span({ class: 'card-label' }, (i18n.tribeVotationDeadline || 'Deadline') + ':'),
            span({ class: 'card-value' }, v.deadline)
          ) : null,
          div({ class: 'card-field' },
            span({ class: 'card-label' }, (i18n.tribeVotationResults || 'Votes') + ':'),
            span({ class: 'card-value' }, String(totalVotes))
          ),
          br(),
          div({ class: 'tribe-votation-options' },
            opts.map((opt, idx) => {
              const count = Array.isArray(votes[String(idx)]) ? votes[String(idx)].length : 0;
              const pct = totalVotes > 0 ? Math.round((count / totalVotes) * 100) : 0;
              const roundedPct = Math.round(pct / 5) * 5;
              return div({ class: 'tribe-votation-option' },
                span({ class: 'tribe-votation-label' }, opt),
                div({ class: 'tribe-votation-bar' },
                  div({ class: `tribe-votation-fill tribe-fill-${roundedPct}` })
                ),
                span({ class: 'tribe-votation-count' }, `${count} (${pct}%)`),
                isOpen && !hasVoted ? form({ method: 'POST', action: `${tribeUrl}/votations/${encodeURIComponent(v.id)}/vote` },
                  input({ type: 'hidden', name: 'optionIndex', value: String(idx) }),
                  button({ type: 'submit', class: 'filter-btn' }, i18n.tribeVotationVote)
                ) : null
              );
            })
          ),
          v.author === userId ? div({ class: 'tribe-content-actions' },
            isOpen ? form({ method: 'POST', action: `${tribeUrl}/votations/close/${encodeURIComponent(v.id)}` },
              button({ type: 'submit', class: 'tribe-action-btn' }, i18n.tribeVotationClose)
            ) : null,
            form({ method: 'POST', action: `${tribeUrl}/content/delete/${encodeURIComponent(v.id)}` },
              button({ type: 'submit', class: 'tribe-action-btn danger-btn' }, i18n.tribeContentDelete)
            )
          ) : null
        );
      })
  );
};

const renderForumSection = (tribe, items, query) => {
  const allItems = Array.isArray(items) ? items : [];
  const threads = allItems.filter(i => i.contentType === 'forum');
  const action = query.action;
  const threadId = query.thread;
  const tribeUrl = `/tribe/${encodeURIComponent(tribe.id)}`;

  if (action === 'create') {
    return renderCreateForm(tribe, 'forum', [
      { name: 'title', label: i18n.tribeForumTitle, required: true, placeholder: i18n.tribeForumTitle },
      { name: 'description', type: 'textarea', label: i18n.tribeForumText, required: true, placeholder: i18n.tribeForumText, rows: 6 },
      { name: 'category', type: 'select', label: i18n.tribeForumCategory, options: [
        { value: 'GENERAL', label: i18n.tribeForumCatGeneral }, { value: 'PROPOSAL', label: i18n.tribeForumCatProposal },
        { value: 'QUESTION', label: i18n.tribeForumCatQuestion }, { value: 'ANNOUNCEMENT', label: i18n.tribeForumCatAnnouncement }
      ]}
    ]);
  }

  if (threadId) {
    const thread = allItems.find(i => i.id === threadId);
    const replies = allItems.filter(i => i.contentType === 'forum-reply' && i.parentId === threadId)
      .sort((a, b) => (a.refeeds || 0) - (b.refeeds || 0) !== 0 ? (b.refeeds || 0) - (a.refeeds || 0) : (Date.parse(a.createdAt) || 0) - (Date.parse(b.createdAt) || 0));
    if (!thread) return p(i18n.tribeForumEmpty);
    const replyCount = replies.length;
    return div({ class: 'tribe-content-list' },
      form({ method: 'GET', action: tribeUrl },
        input({ type: 'hidden', name: 'section', value: 'forum' }),
        button({ type: 'submit', class: 'filter-btn' }, i18n.walletBack)
      ),
      div({ class: 'forum-card forum-thread-header' },
        div({ class: 'forum-score-col' },
          div({ class: 'forum-score-box' },
            form({ method: 'POST', action: `${tribeUrl}/forum/${encodeURIComponent(thread.id)}/refeed` },
              button({ type: 'submit', class: 'score-btn' }, '▲')
            ),
            div({ class: 'score-total' }, String(thread.refeeds || 0)),
          )
        ),
        div({ class: 'forum-main-col' },
          div({ class: 'forum-header-row' },
            thread.category ? span({ class: 'forum-category' }, `[${forumCatI18n()[thread.category] || thread.category}]`) : null,
            span({ class: 'forum-title' }, thread.title)
          ),
          div({ class: 'forum-footer' },
            span({ class: 'date-link' }, `${new Date(thread.createdAt).toLocaleString()} ${i18n.performed || ''}`),
            userLink(thread.author)
          ),
          div({ class: 'forum-body' }, ...renderUrl(thread.description || '')),
          div({ class: 'forum-meta' },
            span({ class: 'forum-positive-votes' }, `▲: ${thread.refeeds || 0}`),
            span({ class: 'forum-messages' }, `${(i18n.forumMessages || i18n.tribeForumReplies || 'MESSAGES').toUpperCase()}: ${replyCount}`)
          )
        )
      ),
      div({ class: 'tribe-forum-reply-form' },
        form({ method: 'POST', action: `${tribeUrl}/forum/${encodeURIComponent(threadId)}/reply` },
          textarea({ name: 'description', rows: 3, required: true, placeholder: i18n.tribeForumReply }),
          br(),
          button({ type: 'submit', class: 'forum-send-btn' }, i18n.tribeForumReply)
        )
      ),
      replies.length > 0
        ? replies.map((r, idx) =>
            div({ class: `forum-comment${idx === 0 ? ' highlighted-reply' : ''}` },
              div({ class: 'comment-header' },
                span({ class: 'date-link' }, `${new Date(r.createdAt).toLocaleString()} ${i18n.performed || ''}`),
                userLink(r.author),
                div({ class: 'comment-votes' },
                  span({ class: 'forum-positive-votes' }, `▲: ${r.refeeds || 0}`)
                )
              ),
              div({ class: 'comment-body-row' },
                div({ class: 'comment-vote-col' },
                  div({ class: 'forum-score-box' },
                    form({ method: 'POST', action: `${tribeUrl}/forum/${encodeURIComponent(r.id)}/refeed` },
                      button({ type: 'submit', class: 'score-btn' }, '▲')
                    ),
                    div({ class: 'score-total' }, String(r.refeeds || 0))
                  )
                ),
                div({ class: 'comment-text-col' },
                  ...(r.description || '').split('\n').map(l => l.trim()).filter(l => l).map(l => p(...renderUrl(l)))
                )
              ),
              r.author === userId ? div({ class: 'tribe-content-actions' },
                form({ method: 'POST', action: `${tribeUrl}/content/delete/${encodeURIComponent(r.id)}` },
                  button({ type: 'submit', class: 'tribe-action-btn danger-btn' }, i18n.tribeContentDelete)
                )
              ) : null
            )
          )
        : null
    );
  }

  const replyMap = new Map();
  allItems.filter(i => i.contentType === 'forum-reply').forEach(r => { replyMap.set(r.parentId, (replyMap.get(r.parentId) || 0) + 1); });
  const sortedThreads = [...threads].sort((a, b) => ((b.refeeds || 0) + (replyMap.get(b.id) || 0)) - ((a.refeeds || 0) + (replyMap.get(a.id) || 0)));

  return div({ class: 'tribe-content-list' },
    div({ class: 'tribe-content-header' },
      h2(i18n.tribeSectionForum),
      form({ method: 'GET', action: tribeUrl },
        input({ type: 'hidden', name: 'section', value: 'forum' }),
        input({ type: 'hidden', name: 'action', value: 'create' }),
        button({ type: 'submit', class: 'create-button' }, i18n.tribeForumCreate)
      )
    ),
    sortedThreads.length === 0 ? p(i18n.tribeForumEmpty) :
      div({ class: 'forum-list' },
        sortedThreads.map(t => {
          const replyCount = allItems.filter(i => i.contentType === 'forum-reply' && i.parentId === t.id).length;
          return div({ class: 'forum-card' },
            div({ class: 'forum-score-col' },
              div({ class: 'forum-score-box' },
                form({ method: 'POST', action: `${tribeUrl}/forum/${encodeURIComponent(t.id)}/refeed` },
                  button({ type: 'submit', class: 'score-btn' }, '▲')
                ),
                div({ class: 'score-total' }, String(t.refeeds || 0))
              )
            ),
            div({ class: 'forum-main-col' },
              div({ class: 'forum-header-row' },
                t.category ? span({ class: 'forum-category' }, `[${forumCatI18n()[t.category] || t.category}]`) : null,
                form({ method: 'GET', action: tribeUrl, class: 'forum-title-form' },
                  input({ type: 'hidden', name: 'section', value: 'forum' }),
                  input({ type: 'hidden', name: 'thread', value: t.id }),
                  button({ type: 'submit', class: 'forum-title' }, t.title)
                )
              ),
              t.description ? div({ class: 'forum-body' }, ...renderUrl((t.description || '').substring(0, 200))) : null,
              div({ class: 'forum-meta' },
                span({ class: 'forum-positive-votes' }, `▲: ${t.refeeds || 0}`),
                span({ class: 'forum-messages' }, `${(i18n.forumMessages || i18n.tribeForumReplies || 'MESSAGES').toUpperCase()}: ${replyCount}`)
              ),
              div({ class: 'forum-footer' },
                span({ class: 'date-link' }, `${new Date(t.createdAt).toLocaleString()} ${i18n.performed || ''}`),
                userLink(t.author)
              ),
              t.author === userId ? div({ class: 'forum-owner-actions' },
                form({ method: 'POST', action: `${tribeUrl}/content/delete/${encodeURIComponent(t.id)}`, class: 'forum-delete-form' },
                  button({ type: 'submit', class: 'tribe-action-btn danger-btn' }, i18n.tribeContentDelete)
                )
              ) : null
            )
          );
        })
      )
  );
};

const sectionKeyForMediaType = { image: 'images', audio: 'audios', video: 'videos', document: 'documents', bookmark: 'bookmarks', torrent: 'torrents' };
const acceptForMediaType = { image: 'image/*', audio: 'audio/*', video: 'video/*', document: 'application/pdf,.pdf,.doc,.docx,.txt,.odt', bookmark: null, torrent: '.torrent' };
const sectionTitleForMediaType = (mt) => {
  const map = { image: i18n.tribeSectionImages, audio: i18n.tribeSectionAudios, video: i18n.tribeSectionVideos, document: i18n.tribeSectionDocuments, bookmark: i18n.tribeSectionBookmarks, torrent: i18n.tribeSectionTorrents };
  return map[mt] || mt;
};

const renderTribeMediaTypeSection = (tribe, items, query, mediaType) => {
  const allMedia = Array.isArray(items) ? items : [];
  const media = allMedia.filter(m => m.mediaType === mediaType);
  const action = query.action;
  const tribeUrl = `/tribe/${encodeURIComponent(tribe.id)}`;
  const sectionKey = sectionKeyForMediaType[mediaType] || 'media';
  const sTitle = sectionTitleForMediaType(mediaType);
  const createMediaLabel = {
    image: () => i18n.tribeCreateImage || 'Create Image',
    audio: () => i18n.tribeCreateAudio || 'Create Audio',
    video: () => i18n.tribeCreateVideo || 'Create Video',
    document: () => i18n.tribeCreateDocument || 'Create Document',
    bookmark: () => i18n.tribeCreateBookmark || 'Create Bookmark',
    torrent: () => i18n.tribeCreateTorrent || 'Upload Torrent',
  };
  const mediaBtnLabel = createMediaLabel[mediaType] ? createMediaLabel[mediaType]() : i18n.tribeCreateButton;

  if (action === 'create') {
    if (mediaType === 'bookmark') {
      return div({ class: 'create-tribe-form' },
        form({ method: 'POST', action: `${tribeUrl}/media/upload` },
          input({ type: 'hidden', name: 'mediaType', value: 'bookmark' }),
          input({ type: 'hidden', name: 'returnSection', value: sectionKey }),
          label({ for: 'title' }, i18n.tribeMediaTitle), br,
          input({ type: 'text', name: 'title', maxlength: '100', id: 'title', required: true, placeholder: i18n.tribeMediaTitle }), br(),
          label({ for: 'url' }, i18n.bookmarkUrlLabel || 'URL'), br,
          input({ type: 'url', name: 'url', id: 'url', required: true, placeholder: 'https://' }), br(),br(),
          label({ for: 'description' }, i18n.tribeMediaDescription), br,
          textarea({ name: 'description', id: 'description', rows: 3, placeholder: i18n.tribeMediaDescription }, ''), br(),
          button({ type: 'submit', class: 'create-button' }, mediaBtnLabel)
        )
      );
    }
    return div({ class: 'create-tribe-form' },
      form({ method: 'POST', action: `${tribeUrl}/media/upload`, enctype: 'multipart/form-data' },
        input({ type: 'hidden', name: 'mediaType', value: mediaType }),
        input({ type: 'hidden', name: 'returnSection', value: sectionKey }),
        label({ for: 'title' }, i18n.tribeMediaTitle), br,
        input({ type: 'text', name: 'title', maxlength: '100', id: 'title', required: true, placeholder: i18n.tribeMediaTitle }), br(),
        label({ for: 'description' }, i18n.tribeMediaDescription), br,
        textarea({ name: 'description', id: 'description', rows: 3, placeholder: i18n.tribeMediaDescription }, ''), br(),
        label({ for: 'media' }, i18n.tribeMediaUpload), br,
        input({ type: 'file', name: 'media', id: 'media', accept: acceptForMediaType[mediaType] || '*/*', required: true }), br(), br(),
        button({ type: 'submit', class: 'create-button' }, mediaBtnLabel)
      )
    );
  }

  const mediaFooter = (m) => [
    p({ class: 'tribe-media-date' }, span({ class: 'date-link' }, new Date(m.createdAt).toLocaleString())),
    p({ class: 'tribe-media-author' }, userLink(m.author)),
    m.author === userId ? form({ method: 'POST', action: `${tribeUrl}/content/delete/${encodeURIComponent(m.id)}` },
      button({ type: 'submit', class: 'tribe-action-btn danger-btn' }, i18n.tribeContentDelete)
    ) : null
  ];

  const renderMediaItem = (m) => {
    const blobUrl = toBlobUrl(m.image);
    if (mediaType === 'image') {
      return div({ class: 'tribe-media-item' },
        blobUrl ? a({ href: blobUrl, target: '_blank' }, img({ src: blobUrl, alt: m.title || '', class: 'tribe-media-thumb' })) : null,
        div({ class: 'tribe-media-item-info' },
          m.title ? h2(m.title) : null,
          m.description ? p(...renderUrl(m.description)) : null,
          ...mediaFooter(m)
        )
      );
    }
    if (mediaType === 'audio') {
      return div({ class: 'tribe-media-item' },
        blobUrl ? audio({ src: blobUrl, controls: true, class: 'tribe-media-audio' }) : p(i18n.tribeMediaEmpty),
        div({ class: 'tribe-media-item-info' },
          m.title ? h2(m.title) : null,
          m.description ? p(...renderUrl(m.description)) : null,
          ...mediaFooter(m)
        )
      );
    }
    if (mediaType === 'video') {
      return div({ class: 'tribe-media-item' },
        blobUrl ? video({ src: blobUrl, controls: true, class: 'tribe-media-thumb' }) : p(i18n.tribeMediaEmpty),
        div({ class: 'tribe-media-item-info' },
          m.title ? h2(m.title) : null,
          m.description ? p(...renderUrl(m.description)) : null,
          ...mediaFooter(m)
        )
      );
    }
    if (mediaType === 'document') {
      return div({ class: 'tribe-media-item' },
        blobUrl ? a({ href: blobUrl, target: '_blank', class: 'tribe-action-btn' }, i18n.readDocument || 'Read Document') : p(i18n.tribeMediaEmpty),
        div({ class: 'tribe-media-item-info' },
          m.title ? h2(m.title) : null,
          m.description ? p(...renderUrl(m.description)) : null,
          ...mediaFooter(m)
        )
      );
    }
    if (mediaType === 'bookmark') {
      const url = m.url || m.description || '';
      return div({ class: 'tribe-media-item' },
        div({ class: 'tribe-media-item-info' },
          m.title ? h2(m.title) : null,
          url ? div({ class: 'card-field' },
            span({ class: 'card-label' }, 'URL:'),
            a({ href: url, target: '_blank', class: 'card-value' }, url)
          ) : null,
          m.description && m.description !== url ? p(...renderUrl(m.description)) : null,
          ...mediaFooter(m)
        )
      );
    }
    if (mediaType === 'torrent') {
      return div({ class: 'tribe-media-item' },
        blobUrl ? a({ href: blobUrl, class: 'tribe-action-btn' }, i18n.torrentDownloadButton || 'DOWNLOAD IT!') : p(i18n.tribeMediaEmpty),
        div({ class: 'tribe-media-item-info' },
          m.title ? h2(m.title) : null,
          m.description ? p(...renderUrl(m.description)) : null,
          ...mediaFooter(m)
        )
      );
    }
    return null;
  };

  return div({ class: 'tribe-content-list' },
    div({ class: 'tribe-content-header' },
      h2(sTitle),
      form({ method: 'GET', action: tribeUrl },
        input({ type: 'hidden', name: 'section', value: sectionKey }),
        input({ type: 'hidden', name: 'action', value: 'create' }),
        button({ type: 'submit', class: 'create-button' }, mediaBtnLabel)
      )
    ),
    media.length === 0 ? p(i18n.tribeMediaEmpty) :
      div({ class: 'tribe-media-grid' }, media.map(renderMediaItem))
  );
};

const renderSubTribesSection = (tribe, items, query) => {
  const action = query.action;
  const isMemberSub = Array.isArray(tribe.members) && tribe.members.includes(userId);
  const isAuthorSub = tribe.author === userId;
  const canCreate = tribe.inviteMode === 'open' ? (isMemberSub || isAuthorSub) : isAuthorSub;

  if (action === 'create' && canCreate) {
    return renderCreateForm(tribe, 'subtribes', [
      { name: 'title', label: i18n.tribeTitleLabel, required: true, placeholder: 'Name of the sub-tribe' },
      { name: 'description', type: 'textarea', label: i18n.tribeDescriptionLabel, required: true, placeholder: 'Description of the sub-tribe' },
      { name: 'location', label: i18n.tribeLocationLabel, placeholder: 'Where is this sub-tribe located?' },
      { name: 'mapUrl', label: i18n.mapLocationTitle || 'Map Location', placeholder: i18n.mapUrlPlaceholder || '/maps/MAP_ID', spaceBefore: true },
      { name: 'image', type: 'file', label: i18n.tribeImageLabel },
      { name: 'tags', label: i18n.tribeTagsLabel, placeholder: i18n.tribeTagsPlaceholder, spaceBefore: true },
      { name: 'inviteMode', type: 'select', label: i18n.tribeModeLabel, options: [
        { value: 'open', label: i18n.tribeOpen }, { value: 'strict', label: i18n.tribeStrict }
      ], spaceBefore: true },
    ]);
  }

  const subTribes = Array.isArray(items) ? items : [];
  const tribeUrl = `/tribe/${encodeURIComponent(tribe.id)}`;

  return div({ class: 'tribe-content-list' },
    canCreate ? form({ method: 'GET', action: tribeUrl },
      input({ type: 'hidden', name: 'section', value: 'subtribes' }),
      input({ type: 'hidden', name: 'action', value: 'create' }),
      button({ type: 'submit', class: 'tribe-action-btn' }, i18n.tribeSubTribesCreate)
    ) : null,
    !canCreate && tribe.inviteMode === 'strict'
      ? p({ class: 'tribe-strict-denied' }, i18n.tribeSubTribesStrictDenied)
      : null,
    subTribes.length === 0
      ? null
      : div({ class: 'tribe-thumb-grid' },
          subTribes.map(st => {
            return a({ href: `/tribe/${encodeURIComponent(st.id)}`, class: 'tribe-thumb-link', title: st.title },
              img({ src: toImageUrl(st.image, '/assets/images/default-tribe.png'), class: 'tribe-thumb-img', alt: st.title })
            );
          })
        )
  );
};

const renderTribeMapsSection = (tribe, maps) => {
  const items = Array.isArray(maps) ? maps : [];
  const createBtn = form({ method: 'GET', action: '/maps' },
    input({ type: 'hidden', name: 'filter', value: 'create' }),
    input({ type: 'hidden', name: 'tribeId', value: tribe.id }),
    button({ type: 'submit', class: 'create-button' }, i18n.mapUploadButton || 'Create Map'));
  if (items.length === 0) return div({ class: 'tribe-content-list' }, div({ class: 'tribe-content-header' }, h2(i18n.tribeSectionMaps || 'MAPS'), createBtn), p(i18n.noMaps || 'No maps yet'));
  return div({ class: 'tribe-content-list' },
    div({ class: 'tribe-content-header' }, h2(i18n.tribeSectionMaps || 'MAPS'), createBtn),
    items.map(m =>
      div({ class: 'card card-rpg tribe-card-padded' },
        div({ class: 'card-header' },
          h2({ class: 'card-label' }, `[${(i18n.typeMap || 'MAP').toUpperCase()}]`),
          form({ method: 'GET', action: `/maps/${encodeURIComponent(m.key)}` },
            button({ type: 'submit', class: 'filter-btn' }, i18n.viewDetails || 'View Details'))
        ),
        div({ class: 'tribe-card-body' },
          m.title ? div({ class: 'card-field' },
            span({ class: 'card-label' }, (i18n.title || 'Title') + ':'),
            span({ class: 'card-value' }, a({ href: `/maps/${encodeURIComponent(m.key)}` }, m.title))
          ) : null,
          m.description ? p(m.description.substring(0, 200)) : null,
          m.lat && m.lng ? span({ class: 'map-coords' }, `📍 ${m.lat.toFixed(4)}, ${m.lng.toFixed(4)}`) : null
        ),
        p({ class: 'card-footer' },
          span({ class: 'date-link' }, new Date(m.createdAt).toLocaleString()),
          userLink(m.author)
        )
      )
    )
  );
};

const renderTribeTorrentsSection = (tribe, torrents) => {
  const items = Array.isArray(torrents) ? torrents : [];
  const createBtn = form({ method: 'GET', action: '/torrents' },
    input({ type: 'hidden', name: 'filter', value: 'create' }),
    input({ type: 'hidden', name: 'tribeId', value: tribe.id }),
    button({ type: 'submit', class: 'create-button' }, i18n.tribeCreateTorrent || 'Upload Torrent'));
  if (items.length === 0) return div({ class: 'tribe-content-list' }, div({ class: 'tribe-content-header' }, h2(i18n.tribeSectionTorrents || 'TORRENTS'), createBtn), p(i18n.tribeTorrentsEmpty || 'No torrents, yet.'));
  return div({ class: 'tribe-content-list' },
    div({ class: 'tribe-content-header' }, h2(i18n.tribeSectionTorrents || 'TORRENTS'), createBtn),
    items.map(m => {
      const blobName = encodeURIComponent((m.title || 'download').replace(/\.torrent$/i, '') + '.torrent');
      const blobUrl = m.url ? `/blob/${encodeURIComponent(m.url)}?name=${blobName}` : null;
      return div({ class: 'card card-rpg tribe-card-padded' },
        div({ class: 'card-header' },
          h2({ class: 'card-label' }, `[${(i18n.typeTorrent || 'TORRENT').toUpperCase()}]`),
          m._isMedia
            ? (blobUrl ? a({ href: blobUrl, class: 'filter-btn' }, i18n.torrentDownload || 'Download') : null)
            : form({ method: 'GET', action: `/torrents/${encodeURIComponent(m.rootId || m.key)}` },
                button({ type: 'submit', class: 'filter-btn' }, i18n.viewDetails || 'View Details'))
        ),
        div({ class: 'tribe-card-body' },
          m.title ? div({ class: 'card-field' },
            span({ class: 'card-label' }, (i18n.title || 'Title') + ':'),
            span({ class: 'card-value' }, m._isMedia
              ? (blobUrl ? a({ href: blobUrl }, m.title) : m.title)
              : a({ href: `/torrents/${encodeURIComponent(m.rootId || m.key)}` }, m.title))
          ) : null,
          m.description ? p(String(m.description).substring(0, 200)) : null,
          blobUrl && !m._isMedia ? div({ class: 'card-field' }, a({ href: blobUrl, class: 'filter-btn' }, i18n.torrentDownload || 'Download')) : null
        ),
        p({ class: 'card-footer' },
          span({ class: 'date-link' }, new Date(m.createdAt).toLocaleString()),
          userLink(m.author)
        )
      );
    })
  );
};

const renderTribePadsSection = (tribe, pads) => {
  const items = Array.isArray(pads) ? pads : [];
  const createBtn = form({ method: 'GET', action: '/pads' },
    input({ type: 'hidden', name: 'filter', value: 'create' }),
    input({ type: 'hidden', name: 'tribeId', value: tribe.id }),
    button({ type: 'submit', class: 'create-button' }, i18n.tribePadCreate || 'Create Pad'));
  if (items.length === 0) return div({ class: 'tribe-content-list' }, div({ class: 'tribe-content-header' }, h2(i18n.tribeSectionPads || 'PADS'), createBtn), p(i18n.tribePadsEmpty || 'No pads, yet.'));
  return div({ class: 'tribe-content-list' },
    div({ class: 'tribe-content-header' }, h2(i18n.tribeSectionPads || 'PADS'), createBtn),
    items.map(m =>
      div({ class: 'card card-rpg tribe-card-padded' },
        div({ class: 'card-header' },
          h2({ class: 'card-label' }, `[${(i18n.typePad || 'PAD').toUpperCase()}]`),
          form({ method: 'GET', action: `/pads/${encodeURIComponent(m.rootId)}` },
            button({ type: 'submit', class: 'filter-btn' }, i18n.viewDetails || 'View Details'))
        ),
        div({ class: 'tribe-card-body' },
          m.title ? div({ class: 'card-field' },
            span({ class: 'card-label' }, (i18n.title || 'Title') + ':'),
            span({ class: 'card-value' }, a({ href: `/pads/${encodeURIComponent(m.rootId)}` }, m.title))
          ) : null
        ),
        p({ class: 'card-footer' },
          span({ class: 'date-link' }, new Date(m.createdAt).toLocaleString()),
          userLink(m.author)
        )
      )
    )
  );
};

const renderTribeChatsSection = (tribe, chats) => {
  const items = Array.isArray(chats) ? chats : [];
  const createBtn = form({ method: 'GET', action: '/chats' },
    input({ type: 'hidden', name: 'filter', value: 'create' }),
    input({ type: 'hidden', name: 'tribeId', value: tribe.id }),
    button({ type: 'submit', class: 'create-button' }, i18n.tribeChatCreate || 'Create Chat'));
  if (items.length === 0) return div({ class: 'tribe-content-list' }, div({ class: 'tribe-content-header' }, h2(i18n.tribeSectionChats || 'CHATS'), createBtn), p(i18n.tribeChatsEmpty || 'No chats, yet.'));
  return div({ class: 'tribe-content-list' },
    div({ class: 'tribe-content-header' }, h2(i18n.tribeSectionChats || 'CHATS'), createBtn),
    items.map(m =>
      div({ class: 'card card-rpg tribe-card-padded' },
        div({ class: 'card-header' },
          h2({ class: 'card-label' }, `[${(i18n.typeChat || 'CHAT').toUpperCase()}]`),
          form({ method: 'GET', action: `/chats/${encodeURIComponent(m.key)}` },
            button({ type: 'submit', class: 'filter-btn' }, i18n.viewDetails || 'View Details'))
        ),
        div({ class: 'tribe-card-body' },
          m.title ? div({ class: 'card-field' },
            span({ class: 'card-label' }, (i18n.title || 'Title') + ':'),
            span({ class: 'card-value' }, a({ href: `/chats/${encodeURIComponent(m.key)}` }, m.title))
          ) : null,
          m.description ? p(m.description.substring(0, 200)) : null
        ),
        p({ class: 'card-footer' },
          span({ class: 'date-link' }, new Date(m.createdAt).toLocaleString()),
          userLink(m.author)
        )
      )
    )
  );
};

const renderTribeCalendarsSection = (tribe, calendars) => {
  const items = Array.isArray(calendars) ? calendars : [];
  const createBtn = form({ method: 'GET', action: '/calendars' },
    input({ type: 'hidden', name: 'filter', value: 'create' }),
    input({ type: 'hidden', name: 'tribeId', value: tribe.id }),
    button({ type: 'submit', class: 'create-button' }, i18n.tribeCalendarCreate || 'Create Calendar'));
  if (items.length === 0) return div({ class: 'tribe-content-list' }, div({ class: 'tribe-content-header' }, h2(i18n.tribeSectionCalendars || 'CALENDARS'), createBtn), p(i18n.tribeCalendarsEmpty || 'No calendars, yet.'));
  return div({ class: 'tribe-content-list' },
    div({ class: 'tribe-content-header' }, h2(i18n.tribeSectionCalendars || 'CALENDARS'), createBtn),
    items.map(m =>
      div({ class: 'card card-rpg tribe-card-padded' },
        div({ class: 'card-header' },
          h2({ class: 'card-label' }, `[${(i18n.typeCalendar || 'CALENDAR').toUpperCase()}]`),
          form({ method: 'GET', action: `/calendars/${encodeURIComponent(m.rootId)}` },
            button({ type: 'submit', class: 'filter-btn' }, i18n.viewDetails || 'View Details'))
        ),
        div({ class: 'tribe-card-body' },
          m.title ? div({ class: 'card-field' },
            span({ class: 'card-label' }, (i18n.title || 'Title') + ':'),
            span({ class: 'card-value' }, a({ href: `/calendars/${encodeURIComponent(m.rootId)}` }, m.title))
          ) : null,
          m.deadline ? div({ class: 'card-field' },
            span({ class: 'card-label' }, (i18n.calendarDeadlineLabel || 'Deadline') + ':'),
            span({ class: 'card-value' }, new Date(m.deadline).toLocaleDateString())
          ) : null
        ),
        p({ class: 'card-footer' },
          span({ class: 'date-link' }, new Date(m.createdAt).toLocaleString()),
          userLink(m.author)
        )
      )
    )
  );
};

exports.tribeView = async (tribe, userIdParam, query, section, sectionData) => {
  if (!tribe) {
    return div({ class: 'error' }, i18n.tribeNotFound);
  }

  section = section || 'activity';
  sectionData = sectionData || {};

  const imageSrc = tribe.image;
  const pageTitle = tribe.title;

  let sectionContent;
  switch (section) {
    case 'inhabitants': sectionContent = renderInhabitantsSection(tribe, sectionData); break;
    case 'feed':
      sectionContent = div(
        query.sent ? div({ class: 'card card-rpg tribe-banner' },
          p({ class: 'bold' }, i18n.tribeFeedSent || 'Message sent successfully!')
        ) : null,
        tribe.members.includes(config.keys.id)
          ? form({ class: 'tribe-feed-compose', method: 'POST', action: `/tribe/${encodeURIComponent(tribe.id)}/message` },
              textarea({ name: 'message', rows: 4, maxlength: MAX_MESSAGE_LENGTH, placeholder: i18n.tribeFeedMessagePlaceholder }),
              button({ type: 'submit', class: 'tribe-feed-send' }, i18n.tribeFeedSend)
            )
          : null,
        await renderFeedTribeView(sectionData, tribe, query, query.filter)
      );
      break;
    case 'events': sectionContent = renderEventsSection(tribe, sectionData, query); break;
    case 'tasks': sectionContent = renderTasksSection(tribe, sectionData, query); break;
    case 'votations': sectionContent = renderVotationsSection(tribe, sectionData, query); break;
    case 'polls': sectionContent = renderTribePollsSection(tribe, sectionData, query); break;
    case 'forum': sectionContent = renderForumSection(tribe, sectionData, query); break;
    case 'subtribes': sectionContent = renderSubTribesSection(tribe, sectionData, query); break;
    case 'search': sectionContent = renderTribeSearchSection(tribe, sectionData, query); break;
    case 'images': sectionContent = renderTribeMediaTypeSection(tribe, sectionData, query, 'image'); break;
    case 'audios': sectionContent = renderTribeMediaTypeSection(tribe, sectionData, query, 'audio'); break;
    case 'videos': sectionContent = renderTribeMediaTypeSection(tribe, sectionData, query, 'video'); break;
    case 'documents': sectionContent = renderTribeMediaTypeSection(tribe, sectionData, query, 'document'); break;
    case 'bookmarks': sectionContent = renderTribeMediaTypeSection(tribe, sectionData, query, 'bookmark'); break;
    case 'torrents': sectionContent = renderTribeTorrentsSection(tribe, sectionData); break;
    case 'maps': sectionContent = renderTribeMapsSection(tribe, sectionData); break;
    case 'pads': sectionContent = renderTribePadsSection(tribe, sectionData); break;
    case 'chats': sectionContent = renderTribeChatsSection(tribe, sectionData); break;
    case 'calendars': sectionContent = renderTribeCalendarsSection(tribe, sectionData); break;
    case 'governance': sectionContent = renderGovernance(tribe, sectionData); break;
    case 'trending': sectionContent = renderTribeTrendingSection(tribe, sectionData, query); break;
    case 'tags': sectionContent = renderTribeTagsSection(tribe, sectionData, query); break;
    case 'activity':
    default: sectionContent = renderTribeActivitySection(tribe, sectionData); break;
  }

  const subTribes = Array.isArray(tribe.subTribes) ? tribe.subTribes : [];
  const isMemberOfTribe = Array.isArray(tribe.members) && tribe.members.includes(userId);
  const isAuthorOfTribe = tribe.author === userId;
  const isOutsider = !isMemberOfTribe && !isAuthorOfTribe;
  const canCreateSub = !tribe.parentTribeId && (tribe.inviteMode === 'open' ? (isMemberOfTribe || isAuthorOfTribe) : isAuthorOfTribe);
  const isLarpHouse = isLarpHouseTribe(tribe);
  const larpHouseKey = tribe.larpHouseKey || null;
  const canGenerateInvite = isLarpHouse
    ? (isMemberOfTribe && !!larpHouseKey && larpHouseKey !== 'academia')
    : (isAuthorOfTribe || (tribe.inviteMode === 'open' && isMemberOfTribe));
  const canLeave = isMemberOfTribe && (isLarpHouse || !isAuthorOfTribe);
  const showOwnerControls = !isLarpHouse && isAuthorOfTribe;
  const inviteHref = isLarpHouse ? '/invites#invites-houses' : '/invites#invites-tribes';
  const showInviteTop = isOutsider && !tribe.parentTribeId;
  const hasOpenInvite = !!tribe.openInviteCode;
  const canManageOpenInvite = hasOpenInvite && (tribe.openInviteBy === userId || isAuthorOfTribe);
  const hasSideActions = canGenerateInvite || showOwnerControls || canLeave || (isOutsider && !showInviteTop);

  const tribeDetails = div({ class: 'tribe-details' },
    div({ class: 'tribe-side' },
      tribe.parentTribe
        ? div({ class: 'tribe-parent-box' },
            h2({ class: 'tribe-info-label' }, i18n.tribeMainTribeLabel || 'MAIN TRIBE'),
            a({ href: `/tribe/${encodeURIComponent(tribe.parentTribe.id)}`, class: 'tribe-parent-link' },
              img({ src: toBlobUrl(tribe.parentTribe.image) || '/assets/images/default-tribe.png', alt: tribe.parentTribe.title, class: 'tribe-parent-image' })
            )
          )
        : null,
      div({ class: 'shop-title-row' },
        h2({ class: 'tribe-card-title' }, tribe.title)
      ),
      div({ class: 'card-chips-row' },
        tribe.isAnonymous ? renderPrivacyChip(true, i18n) : renderPrivacyChip(false, i18n),
        tribe.isAnonymous ? renderTribeEncryptedChip(i18n) : null,
        renderModeChip(tribe.inviteMode, i18n),
        renderLifespanChip(tribe.lifetime, i18n)
      ),
      renderMediaBlob(imageSrc, '/assets/images/default-tribe.png', { alt: tribe.title, class: 'tribe-detail-image' }),
      table({ class: 'tribe-info-table' },
        tr(
          td({ class: 'tribe-info-label' }, i18n.tribeCreatedAt || 'CREATED'),
          td({ class: 'tribe-info-value', colspan: '3' }, new Date(tribe.createdAt).toLocaleString())
        ),
        tr(
          td({ class: 'tribe-info-value tribe-author-cell', colspan: '4' }, userLink(tribe.author))
        ),
        tribe.location ? tr(
          td({ class: 'tribe-info-label' }, i18n.tribeLocationLabel || 'LOCATION'),
          td({ class: 'tribe-info-value', colspan: '3' }, ...renderUrl(tribe.location))
        ) : null
      ),
      h2({ class: 'tribe-members-count' }, `${i18n.tribeMembersCount}: ${tribe.memberCount != null ? tribe.memberCount : tribe.members.length}`),
      (canGenerateInvite || (isOutsider && !showInviteTop)) ? div({ class: 'tribe-side-actions' },
        canGenerateInvite
          ? (isLarpHouse
              ? form({ method: 'POST', action: '/larp/invite/create' },
                  input({ type: 'hidden', name: 'houseKey', value: larpHouseKey }),
                  button({ type: 'submit', class: 'tribe-action-btn' }, i18n.tribeGenerateInvite)
                )
              : form({ method: 'POST', action: '/tribes/generate-invite' },
                  input({ type: 'hidden', name: 'tribeId', value: tribe.id }),
                  button({ type: 'submit', class: 'tribe-action-btn' }, i18n.tribeGenerateInvite)
                ))
          : null,
        (canGenerateInvite && !hasOpenInvite)
          ? form({ method: 'POST', action: '/tribes/open-invite/create' },
              input({ type: 'hidden', name: 'tribeId', value: tribe.id }),
              button({ type: 'submit', class: 'tribe-action-btn' }, i18n.tribeOpenInvitation)
            )
          : null,
        (isOutsider && !showInviteTop)
          ? a({ class: 'tribe-action-btn', href: inviteHref }, i18n.tribeEnterInvite)
          : null
      ) : null,
      (isLarpHouse && larpHouseKey === 'academia' && isOutsider)
        ? div({ class: 'tribe-side-actions' },
            form({ method: 'POST', action: '/larp/join' },
              input({ type: 'hidden', name: 'house', value: 'academia' }),
              input({ type: 'hidden', name: 'returnTo', value: `/tribe/${encodeURIComponent(tribe.id)}` }),
              button({ type: 'submit', class: 'tribe-action-btn' }, i18n.larpInviteRedeem || 'Join House')
            )
          )
        : null,
      (hasOpenInvite && canManageOpenInvite) ? div({ class: 'tribe-open-invite-panel' },
        div({ class: 'tribe-open-invite' },
          span({ class: 'tribe-members-count' }, i18n.tribeInviteCodeText),
          span({ class: 'tribe-open-invite-code' }, tribe.openInviteCode)
        ),
        renderInviteQrCard({ qrDataUrl: tribe.openInviteQr, name: tribe.title }),
        form({ method: 'POST', action: '/tribes/open-invite/remove' },
          input({ type: 'hidden', name: 'tribeId', value: tribe.id }),
          button({ type: 'submit', class: 'tribe-action-btn danger-btn' }, i18n.tribeRemoveInvitation)
        )
      ) : null,
      tribe.description ? p({ class: 'tribe-side-description' }, ...renderUrl(tribe.description)) : null,
      renderMapLocationVisitLabel(tribe.mapUrl),
      (!tribe.parentTribeId && (canCreateSub || subTribes.length > 0 || showInviteTop)) ? div({ class: 'tribe-side-subtribes' },
        canCreateSub
          ? form({ method: 'GET', action: `/tribe/${encodeURIComponent(tribe.id)}` },
              input({ type: 'hidden', name: 'section', value: 'subtribes' }),
              input({ type: 'hidden', name: 'action', value: 'create' }),
              button({ type: 'submit', class: 'tribe-action-btn' }, i18n.tribeSubTribesCreate)
            )
          : null,
        showInviteTop
          ? a({ class: 'tribe-action-btn', href: inviteHref }, i18n.tribeEnterInvite)
          : null,
        subTribes.length > 0
          ? div({ class: 'tribe-subtribes-list' },
              subTribes.map(st =>
                form({ method: 'GET', action: `/tribe/${encodeURIComponent(st.id)}` },
                  button({ type: 'submit', class: 'tribe-subtribe-link' }, st.isAnonymous ? "\uD83D\uDD12 " : "", st.title)
                )
              )
            )
          : null
      ) : null,
      tribe.tags && tribe.tags.filter(Boolean).length ? div({ class: 'tribe-side-tags' }, tribe.tags.filter(Boolean).map(tag =>
        a({ href: `/search?query=%23${encodeURIComponent(tag)}`, class: 'tag-link' }, `#${tag}`)
      )) : null,
      (showOwnerControls || canLeave) ? div({ class: 'tribe-side-actions tribe-side-actions-bottom' },
        showOwnerControls
          ? form({ method: 'GET', action: `/tribes/edit/${encodeURIComponent(tribe.id)}` },
              button({ type: 'submit', class: 'tribe-action-btn' }, i18n.tribeUpdateButton)
            )
          : null,
        showOwnerControls
          ? form({ method: 'POST', action: `/tribes/delete/${encodeURIComponent(tribe.id)}` },
              button({ type: 'submit', class: 'tribe-action-btn danger-btn' }, i18n.tribeDeleteButton)
            )
          : null,
        canLeave
          ? (isLarpHouse
              ? form({ method: 'POST', action: '/larp/leave' },
                  button({ type: 'submit', class: 'tribe-action-btn danger-btn' }, i18n.tribeLeaveButton)
                )
              : form({ method: 'POST', action: `/tribes/leave/${encodeURIComponent(tribe.id)}` },
                  button({ type: 'submit', class: 'tribe-action-btn danger-btn' }, i18n.tribeLeaveButton)
                ))
          : null
      ) : null,
    ),
    div({ class: 'tribe-main' },
      query.inviteCode ? div({ class: 'card card-rpg tribe-banner' },
        p({ class: 'bold' }, i18n.tribeInviteCodeText, query.inviteCode)
      ) : null,
      renderSectionNav(tribe, section),
      sectionContent
    )
  );

  return template(
    pageTitle,
    tribeDetails
  );
};

const GOVERNANCE_METHODS = ['DEMOCRACY', 'MAJORITY', 'MINORITY', 'DICTATORSHIP', 'KARMATOCRACY'];

const governanceFilterBar = (tribeId, currentFilter, showPublish) => {
  const row1 = [
    { key: 'government', label: i18n.tribeGovFilterGovernment || 'GOVERNMENT' },
    { key: 'candidatures', label: i18n.tribeGovFilterCandidatures || 'CANDIDATURES' },
    { key: 'proposals', label: i18n.tribeGovProposals || 'PROPOSALS' },
    { key: 'laws', label: i18n.tribeGovFilterLaws || 'LAWS' }
  ];
  const row2 = [
    { key: 'revocations', label: i18n.tribeGovRevocations || 'REVOCATIONS' },
    { key: 'historical', label: i18n.tribeGovHistorical || 'HISTORICAL' },
    { key: 'leaders', label: i18n.tribeGovLeader || 'LEADERS' },
    { key: 'rules', label: i18n.tribeGovRules || 'RULES' }
  ];
  const mkRow = (filters) => div({ class: 'mode-buttons-row' },
    filters.map(f =>
      form({ method: 'GET', action: `/tribe/${encodeURIComponent(tribeId)}` },
        input({ type: 'hidden', name: 'section', value: 'governance' }),
        input({ type: 'hidden', name: 'filter', value: f.key }),
        button({ type: 'submit', class: currentFilter === f.key ? 'filter-btn active' : 'filter-btn' }, f.label)
      )
    )
  );
  return div({ class: 'filters' },
    mkRow(row1),
    mkRow(row2),
    showPublish
      ? div({ class: 'mode-buttons-row' },
          form({ method: 'POST', action: `/tribe/${encodeURIComponent(tribeId)}/governance/publish-candidature` },
            button({ type: 'submit', class: 'create-button' }, i18n.tribeGovCandidatureProposeBtn || 'Publish Candidature')
          )
        )
      : null
  );
};

const fmtTermDate = (d) => d ? moment(d).format('YYYY-MM-DD HH:mm:ss') : '—';
const fmtTimeLeft = (end) => {
  if (!end) return '—';
  const diff = moment(end).diff(moment());
  if (diff <= 0) return '0d 00:00:00';
  const dur = moment.duration(diff);
  const d = Math.floor(dur.asDays());
  const h = String(dur.hours()).padStart(2, '0');
  const m = String(dur.minutes()).padStart(2, '0');
  const s = String(dur.seconds()).padStart(2, '0');
  return `${d}d ${h}:${m}:${s}`;
};
const methodImageSrc = (method) => `/assets/images/${String(method || '').toLowerCase()}.png`;

const governmentCard = (tribe, term, leaders) => {
  if (!term) {
    return div({ class: 'card' },
      h3(i18n.tribeGovernanceNoGov || 'No active government'),
      p(i18n.tribeGovernanceNoGovDesc || 'This tribe has not yet elected a government. Propose candidatures to start the process.')
    );
  }
  const method = String(term.method || 'ANARCHY').toUpperCase();
  const isAnarchy = method === 'ANARCHY';
  const i18nMeth = i18n[`parliamentMethod${method}`];
  const methodLabel = (i18nMeth && String(i18nMeth).trim() ? String(i18nMeth) : method).toUpperCase();
  const termStart = term.startAt || null;
  const termEnd = term.endAt || null;
  const population = tribe.memberCount != null ? tribe.memberCount : (Array.isArray(tribe.members) ? tribe.members.length : 0);
  const winnerVotes = Number(term.winnerVotes || 0);
  const totalVotes = Number(term.totalVotes || 0);
  const votesDisplay = `${winnerVotes} (${totalVotes})`;
  const leaderId = term.leaderId || (Array.isArray(leaders) && leaders[0]) || null;
  return div({ class: 'card' },
    h2(i18n.tribeGovCardTitle || 'Current Government'),
    div({ class: 'cycle-info' },
      div({ class: 'kpi' },
        span({ class: 'kpi__label' }, ((i18n.tribeGovCycleSince || 'CYCLE SINCE') + ': ').toUpperCase()),
        span({ class: 'kpi__value' }, fmtTermDate(termStart))
      ),
      div({ class: 'kpi' },
        span({ class: 'kpi__label' }, ((i18n.tribeGovCycleEnd || 'CYCLE END') + ': ').toUpperCase()),
        span({ class: 'kpi__value' }, fmtTermDate(termEnd))
      ),
      div({ class: 'kpi' },
        span({ class: 'kpi__label' }, ((i18n.tribeGovTimeRemaining || 'TIME REMAINING') + ': ').toUpperCase()),
        span({ class: 'kpi__value' }, fmtTimeLeft(termEnd))
      ),
      div({ class: 'kpi' },
        span({ class: 'kpi__label' }, ((i18n.tribeGovPopulation || 'POPULATION') + ': ').toUpperCase()),
        span({ class: 'kpi__value' }, String(population))
      ),
      div({ class: 'kpi' },
        span({ class: 'kpi__label' }, ((i18n.tribeGovMethod || 'METHOD') + ': ').toUpperCase()),
        span({ class: 'kpi__value' }, methodLabel)
      ),
      !isAnarchy
        ? div({ class: 'kpi' },
            span({ class: 'kpi__label' }, ((i18n.tribeGovVotesReceived || 'VOTES RECEIVED') + ': ').toUpperCase()),
            span({ class: 'kpi__value' }, votesDisplay)
          )
        : null
    ),
    div({ class: 'method-image-centered' },
      img({ src: methodImageSrc(method), alt: methodLabel })
    ),
    !isAnarchy && leaderId
      ? div({ class: 'tribe-leader-block' },
          h3(i18n.tribeGovLeader || 'LEADER'),
          userLink(leaderId)
        )
      : null
  );
};

const candidaturesBlock = (tribe, candidatures, alreadyPublishedThisGlobalCycle) => {
  const list = (Array.isArray(candidatures) ? candidatures : [])
    .filter(c => (c.status || 'OPEN') === 'OPEN')
    .map(c => {
      const voters = (Array.isArray(c.voters) ? c.voters : []).filter(v => String(v) !== String(c.candidateId));
      return { ...c, votes: voters.length };
    })
    .sort((a, b) => Number(b.votes || 0) - Number(a.votes || 0));
  return div({},
    alreadyPublishedThisGlobalCycle
      ? p({ class: 'notice' }, i18n.tribeGovernanceAlreadyPublished || 'This tribe already has an open candidature in the current global parliament cycle.')
      : null,
    h3(i18n.tribeGovernanceProposeInternal || 'Propose internal candidature'),
    form({ method: 'POST', action: `/tribe/${encodeURIComponent(tribe.id)}/governance/candidature/propose` },
      label({}, i18n.tribeGovCandidatureId || 'Candidate'), br(),
      input({ type: 'text', name: 'candidateId', placeholder: '@...ed25519', required: true }), br(), br(),
      label({}, i18n.tribeGovCandidatureMethod || 'Method'), br(),
      select({ name: 'method' },
        GOVERNANCE_METHODS.map(m => option({ value: m }, i18n[`parliamentMethod${m}`] || m))
      ), br(), br(),
      button({ type: 'submit', class: 'create-button' }, i18n.tribeGovCandidatureProposeBtn || 'Publish Candidature')
    ),
    h3(i18n.tribeGovernanceInternalCandidatures || 'Internal candidatures'),
    list.length === 0
      ? p(i18n.tribeGovernanceNoCandidatures || 'No open candidatures.')
      : ul({}, list.map(c =>
          li({},
            c.candidateId
              ? userLink(c.candidateId)
              : '?',
            ` — ${c.method || 'DEMOCRACY'} — ${c.votes || 0} ${i18n.votes || 'votes'}`,
            ' ',
            form({ method: 'POST', action: `/tribe/${encodeURIComponent(tribe.id)}/governance/candidature/vote`, class: 'inline-form' },
              input({ type: 'hidden', name: 'candidatureId', value: c.id }),
              button({ type: 'submit', class: 'filter-btn' }, i18n.vote || 'Vote')
            )
          )
        ))
  );
};

const rulesBlock = (tribe, rules, isCreator) => div({},
  isCreator
    ? div({},
        h3(i18n.tribeGovernanceAddRule || 'Add rule'),
        form({ method: 'POST', action: `/tribe/${encodeURIComponent(tribe.id)}/governance/rule/add` },
          label({}, i18n.tribeGovRuleTitle || 'Title'), br(),
          input({ type: 'text', name: 'title', maxlength: '100', required: true }), br(), br(),
          label({}, i18n.tribeGovRuleBody || 'Body'), br(),
          textarea({ name: 'body', rows: 4 }), br(), br(),
          button({ type: 'submit', class: 'create-button' }, i18n.save || 'Save')
        )
      )
    : null,
  h3(i18n.tribeGovRules || 'Rules'),
  (!Array.isArray(rules) || rules.length === 0)
    ? p(i18n.tribeGovernanceNoRules || 'No rules yet.')
    : ul({}, rules.map(r =>
        li({},
          span({ class: 'bold' }, r.title || '-'),
          r.body ? p(r.body) : null,
          isCreator
            ? form({ method: 'POST', action: `/tribe/${encodeURIComponent(tribe.id)}/governance/rule/delete`, class: 'inline-form' },
                input({ type: 'hidden', name: 'ruleId', value: r.id }),
                button({ type: 'submit', class: 'filter-btn danger-btn' }, i18n.delete || 'Delete')
              )
            : null
        )
      ))
);

const renderGovernance = (tribe, data) => {
  const { filter, term, candidatures, rules, leaders, isCreator, canPublishToGlobal, alreadyPublishedThisGlobalCycle, hasElectedCandidate } = data || {};
  const f = filter || 'government';
  const header = div({ class: 'tags-header' },
    h2(i18n.tribeSectionGovernance || 'GOVERNANCE'),
    p(i18n.tribeGovernanceDesc || 'Internal governance for this tribe. Propose candidatures, debate rules, elect leaders — mirrors the global Parliament.')
  );
  let body;
  if (f === 'government') body = governmentCard(tribe, term, leaders);
  else if (f === 'candidatures') body = candidaturesBlock(tribe, candidatures, alreadyPublishedThisGlobalCycle);
  else if (f === 'rules') body = rulesBlock(tribe, rules, !!isCreator);
  else if (f === 'leaders') body = div({ class: 'card' },
    h3(i18n.tribeGovLeader || 'LEADERS'),
    (!Array.isArray(leaders) || leaders.length === 0)
      ? p(i18n.tribeGovernanceNoLeaders || 'No leaders elected yet.')
      : ul({}, leaders.map(l => li({}, userLink(l))))
  );
  else {
    const govEmptyMsg = {
      proposals: i18n.tribeGovNoProposals || 'Not any proposal, yet',
      laws: i18n.tribeGovNoLaws || 'Not any law, yet',
      revocations: i18n.tribeGovNoRevocations || 'Not any revocation, yet',
      historical: i18n.tribeGovNoHistorical || 'Not any record, yet'
    };
    body = div({ class: 'card' },
      h3(i18n[`tribeGovFilter${f.charAt(0).toUpperCase()}${f.slice(1)}`] || i18n[`tribeGov${f.charAt(0).toUpperCase()}${f.slice(1)}`] || f.toUpperCase()),
      p(govEmptyMsg[f] || i18n.tribeGovernanceComingSoon || 'Coming soon in this tribe\'s governance module.')
    );
  }

  const showPublish = !!(canPublishToGlobal && hasElectedCandidate && !alreadyPublishedThisGlobalCycle);
  return div({ class: 'tribe-governance' }, header, governanceFilterBar(tribe.id, f, showPublish), body);
};

exports.renderGovernance = renderGovernance;
