const { div, h2, p, section, button, form, a, textarea, br, input, table, tr, th, td, label, span } = require("../server/node_modules/hyperaxe");
const { template, i18n, userLink} = require("./main_views");
const moment = require("../server/node_modules/moment");
const { config } = require("../server/SSB_server.js");
const opinionCategories = require("../backend/opinion_categories");
const { renderUrl } = require("../backend/renderUrl");

const userId = config.keys.id;

const safeArray = (v) => Array.isArray(v) ? v : [];

const voteLabel = (opt) =>
  i18n["vote" + opt.split("_").map(w => w.charAt(0) + w.slice(1).toLowerCase()).join("")] || opt;

const toValueChildren = (v) => {
  if (v === undefined || v === null) return [];
  if (Array.isArray(v)) return v;
  if (typeof v === "string") return renderUrl(v);
  if (typeof v === "number" || typeof v === "boolean") return renderUrl(String(v));
  return [v];
};

const renderCardField = (labelText, valueNode) =>
  div(
    { class: "card-field" },
    span({ class: "card-label" }, labelText),
    span({ class: "card-value" }, ...toValueChildren(valueNode))
  );

const normalizeStatus = (v) => {
  const up = String(v || "").toUpperCase();
  if (up === "OPEN" || up === "CLOSED") return up;
  return up || "OPEN";
};

const statusLabel = (s) => {
  const up = normalizeStatus(s);
  if (up === "OPEN") return i18n.voteStatusOpen || i18n.voteFilterOpen || "OPEN";
  if (up === "CLOSED") return i18n.voteStatusClosed || i18n.voteFilterClosed || "CLOSED";
  return up;
};

const renderVoteOwnerActions = (v, returnTo, mode) => {
  const showUpdateButton = mode === "mine" && !Object.keys(v.opinions || {}).length;
  const showDeleteButton = mode === "mine";

  const actions = [];
  if (showUpdateButton) {
    actions.push(
      form(
        { method: "GET", action: `/votes/edit/${encodeURIComponent(v.id)}` },
        input({ type: "hidden", name: "returnTo", value: returnTo }),
        button({ class: "update-btn", type: "submit" }, i18n.voteUpdateButton)
      )
    );
  }
  if (showDeleteButton) {
    actions.push(
      form(
        { method: "POST", action: `/votes/delete/${encodeURIComponent(v.id)}` },
        input({ type: "hidden", name: "returnTo", value: returnTo }),
        button({ class: "delete-btn", type: "submit" }, i18n.voteDeleteButton)
      )
    );
  }
  return actions;
};

const renderVotePMActions = (v) => {
  if (!v.createdBy || v.createdBy === userId) return [];
  return [
    form(
      { method: "GET", action: "/pm" },
      input({ type: "hidden", name: "recipients", value: v.createdBy }),
      button({ type: "submit", class: "filter-btn" }, i18n.privateMessage)
    )
  ];
};

const renderVoteTopbar = (v, activeFilter, opts = {}) => {
  const isSingle = !!opts.single;
  const currentFilter = activeFilter || "all";

  const returnToList = `/votes?filter=${encodeURIComponent(currentFilter)}`;
  const returnToSelf = `/votes/${encodeURIComponent(v.id)}?filter=${encodeURIComponent(currentFilter)}`;
  const rt = isSingle ? returnToSelf : returnToList;

  const leftActions = [];

  if (!isSingle) {
    leftActions.push(
      form(
        { method: "GET", action: `/votes/${encodeURIComponent(v.id)}` },
        input({ type: "hidden", name: "filter", value: currentFilter }),
        button({ class: "filter-btn", type: "submit" }, i18n.viewDetails)
      )
    );
  }

  leftActions.push(...renderVotePMActions(v));

  const ownerActions = renderVoteOwnerActions(v, rt, opts.mode || "");
  const rightActions = [];
  if (ownerActions.length) rightActions.push(...ownerActions);

  const leftNode = leftActions.length ? div({ class: "bookmark-topbar-left" }, ...leftActions) : null;
  const rightNode = rightActions.length ? div({ class: "bookmark-actions vote-actions" }, ...rightActions) : null;

  const nodes = [];
  if (leftNode) nodes.push(leftNode);
  if (rightNode) nodes.push(rightNode);

  return nodes.length ? div({ class: isSingle ? "bookmark-topbar vote-topbar-single" : "bookmark-topbar" }, ...nodes) : null;
};

const renderVoteButtons = (v, voteOptions, firstRow, secondRow, returnTo) => {
  if (normalizeStatus(v.status) !== "OPEN") return null;

  return div(
    { class: "vote-buttons-block" },
    div(
      { class: "vote-buttons-row" },
      ...firstRow.map((opt) =>
        form(
          { method: "POST", action: `/votes/vote/${encodeURIComponent(v.id)}` },
          input({ type: "hidden", name: "returnTo", value: returnTo }),
          button({ type: "submit", name: "choice", value: opt }, voteLabel(opt))
        )
      )
    ),
    div(
      { class: "vote-buttons-row" },
      ...secondRow.map((opt) =>
        form(
          { method: "POST", action: `/votes/vote/${encodeURIComponent(v.id)}` },
          input({ type: "hidden", name: "returnTo", value: returnTo }),
          button({ type: "submit", name: "choice", value: opt }, voteLabel(opt))
        )
      )
    )
  );
};

const renderOpinionsBar = (v, returnTo) =>
  div(
    { class: "voting-buttons" },
    opinionCategories.map((category) =>
      form(
        { method: "POST", action: `/votes/opinions/${encodeURIComponent(v.id)}/${category}` },
        input({ type: "hidden", name: "returnTo", value: returnTo }),
        button(
          { class: "vote-btn", type: "submit" },
          `${i18n[`vote${category.charAt(0).toUpperCase() + category.slice(1)}`] || category} [${(v.opinions && v.opinions[category]) ? v.opinions[category] : 0}]`
        )
      )
    )
  );

const renderVoteCard = (v, voteOptions, firstRow, secondRow, mode, activeFilter) => {
  const baseCounts = voteOptions.reduce((acc, opt) => {
    acc[opt] = (v.votes && v.votes[opt]) ? v.votes[opt] : 0;
    return acc;
  }, {});

  const maxOpt = voteOptions
    .filter((opt) => opt !== "FOLLOW_MAJORITY")
    .reduce((top, opt) => baseCounts[opt] > baseCounts[top] ? opt : top, "NOT_INTERESTED");

  const totalVotesNum = typeof v.totalVotes === "number" ? v.totalVotes : parseInt(String(v.totalVotes || "0"), 10) || 0;
  const result = totalVotesNum === 0 ? "NOT_INTERESTED" : maxOpt;

  const commentCount = typeof v.commentCount === "number" ? v.commentCount : 0;
  const showCommentsSummaryInCard = mode !== "detail";

  const listReturnTo = `/votes?filter=${encodeURIComponent(activeFilter || "all")}`;
  const detailReturnTo = `/votes/${encodeURIComponent(v.id)}?filter=${encodeURIComponent(activeFilter || "all")}`;
  const returnTo = mode === "detail" ? detailReturnTo : listReturnTo;

  const topbar = renderVoteTopbar(v, activeFilter, { single: mode === "detail", mode });

  return div(
    { class: "card card-section vote" },
    topbar ? topbar : null,
    renderCardField(i18n.voteQuestionLabel + ":", v.question),
    renderCardField(i18n.voteDeadline + ":", v.deadline ? moment(v.deadline).format("YYYY/MM/DD HH:mm:ss") : ""),
    renderCardField(i18n.voteStatus + ":", statusLabel(v.status)),
    br(),
    renderVoteButtons(v, voteOptions, firstRow, secondRow, returnTo),
    renderCardField(i18n.voteTotalVotes + ":", totalVotesNum),
    br(),
    div(
      { class: "vote-table" },
      table(
        tr(...voteOptions.map((opt) => th(voteLabel(opt)))),
        tr(...voteOptions.map((opt) => td(baseCounts[opt])))
      )
    ),
    renderCardField(
      i18n.voteBreakdown + ":",
      span(
        voteLabel(result), " = ", String(baseCounts[result] || 0),
        " + ", voteLabel("FOLLOW_MAJORITY"), ": ", String(baseCounts.FOLLOW_MAJORITY || 0)
      )
    ),
    br(),
    div({ class: "vote-buttons-row" }, h2(voteLabel(result))),
    v.tags && v.tags.filter(Boolean).length
      ? div(
          { class: "card-tags" },
          v.tags.filter(Boolean).map((tag) =>
            a({ href: `/search?query=%23${encodeURIComponent(tag)}`, class: "tag-link" }, `#${tag}`)
          )
        )
      : null,
    showCommentsSummaryInCard
      ? div(
          { class: "card-comments-summary" },
          span({ class: "card-label" }, i18n.voteCommentsLabel + ":"),
          span({ class: "card-value" }, String(commentCount)),
          br(),
          br(),
          form(
            { method: "GET", action: `/votes/${encodeURIComponent(v.id)}` },
            input({ type: "hidden", name: "filter", value: activeFilter || "all" }),
            button({ type: "submit", class: "filter-btn" }, i18n.voteCommentsForumButton)
          )
        )
      : null,
    br(),
    p(
      { class: "card-footer" },
      span({ class: "date-link" }, `${moment(v.createdAt).format("YYYY/MM/DD HH:mm:ss")} ${i18n.performed} `),
      userLink(v.createdBy)
    ),
    renderOpinionsBar(v, returnTo)
  );
};

const renderCommentsSection = (voteId, comments, activeFilter) => {
  const commentsCount = Array.isArray(comments) ? comments.length : 0;
  const returnTo = `/votes/${encodeURIComponent(voteId)}?filter=${encodeURIComponent(activeFilter || "all")}`;

  return div(
    { class: "vote-comments-section" },
    div(
      { class: "comments-count" },
      span({ class: "card-label" }, i18n.voteCommentsLabel + ": "),
      span({ class: "card-value" }, String(commentsCount))
    ),
    div(
      { class: "comment-form-wrapper" },
      h2({ class: "comment-form-title" }, i18n.voteNewCommentLabel),
      form(
        { method: "POST", action: `/votes/${encodeURIComponent(voteId)}/comments`, class: "comment-form", enctype: "multipart/form-data" },
        input({ type: "hidden", name: "returnTo", value: returnTo }),
        textarea({
          id: "comment-text",
          name: "text",
          rows: 4,
          class: "comment-textarea",
          placeholder: i18n.voteNewCommentPlaceholder
        }),
        div({ class: "comment-file-upload" }, label(i18n.uploadMedia), input({ type: "file", name: "blob" })),
        br(),
        button({ type: "submit", class: "comment-submit-btn" }, i18n.voteNewCommentButton)
      )
    ),
    comments && comments.length
      ? div(
          { class: "comments-list" },
          comments.map((c) => {
            const author = c.value && c.value.author ? c.value.author : "";
            const ts = c.value && c.value.timestamp ? c.value.timestamp : c.timestamp;
            const absDate = ts ? moment(ts).format("YYYY/MM/DD HH:mm:ss") : "";
            const relDate = ts ? moment(ts).fromNow() : "";
            const userName = author && author.includes("@") ? author.split("@")[1] : author;

            const content = c.value && c.value.content ? c.value.content : {};
            const root = content.fork || content.root || "";
            const text = content.text || "";

            return div(
              { class: "votations-comment-card" },
              span(
                { class: "created-at" },
                span(i18n.createdBy),
                author ? a({ href: `/author/${encodeURIComponent(author)}` }, `@${userName}`) : span("(unknown)"),
                absDate ? span(" | ") : "",
                absDate ? span({ class: "votations-comment-date" }, absDate) : "",
                relDate ? span({ class: "votations-comment-date" }, " | ", i18n.sendTime) : "",
                relDate && root ? a({ href: `/thread/${encodeURIComponent(root)}#${encodeURIComponent(c.key)}` }, relDate) : ""
              ),
              p({ class: "votations-comment-text" }, ...renderUrl(String(text)))
            );
          })
        )
      : p({ class: "votations-no-comments" }, i18n.voteNoCommentsYet)
  );
};

exports.voteView = async (votes, mode, voteId, comments = [], activeFilterParam) => {
  const list = Array.isArray(votes) ? votes : [votes];

  const standardFilters = ["all", "mine", "open", "closed"];
  const activeFilter = standardFilters.includes(activeFilterParam)
    ? activeFilterParam
    : (standardFilters.includes(mode) ? mode : "all");

  const title =
    mode === "mine" ? i18n.voteMineSectionTitle :
    mode === "create" ? i18n.voteCreateSectionTitle :
    mode === "edit" ? i18n.voteUpdateSectionTitle :
    mode === "open" ? i18n.voteOpenTitle :
    mode === "closed" ? i18n.voteClosedTitle :
    mode === "detail" ? (i18n.voteDetailSectionTitle || i18n.voteAllSectionTitle) :
    i18n.voteAllSectionTitle;

  const voteToEdit = list.find((v) => v.id === voteId) || {};
  const editTags = Array.isArray(voteToEdit.tags) ? voteToEdit.tags.filter(Boolean) : [];

  let filtered =
    mode === "mine" ? list.filter((v) => v.createdBy === userId) :
    mode === "open" ? list.filter((v) => normalizeStatus(v.status) === "OPEN") :
    mode === "closed" ? list.filter((v) => normalizeStatus(v.status) === "CLOSED") :
    list;

  filtered = filtered.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));

  const voteOptions = ["ABSTENTION", "YES", "NO", "CONFUSED", "FOLLOW_MAJORITY", "NOT_INTERESTED"];
  const firstRow = ["ABSTENTION", "YES", "NO"];
  const secondRow = ["CONFUSED", "FOLLOW_MAJORITY", "NOT_INTERESTED"];

  const header = div(
    { class: "tags-header" },
    h2(i18n.votationsTitle),
    p(i18n.votationsDescription)
  );

  const listReturnTo = standardFilters.includes(activeFilter) ? `/votes?filter=${encodeURIComponent(activeFilter)}` : "/votes";

  const deadlineMin = moment().add(1, "minute").format("YYYY-MM-DDTHH:mm");
  const deadlineValue = voteToEdit.deadline ? moment(voteToEdit.deadline).format("YYYY-MM-DDTHH:mm") : "";

  return template(
    title,
    section(
      header,
      div(
        { class: "filters" },
        form(
          { method: "GET", action: "/votes" },
          button({ type: "submit", name: "filter", value: "all", class: mode === "all" ? "filter-btn active" : "filter-btn" }, i18n.voteFilterAll),
          button({ type: "submit", name: "filter", value: "mine", class: mode === "mine" ? "filter-btn active" : "filter-btn" }, i18n.voteFilterMine),
          button({ type: "submit", name: "filter", value: "open", class: mode === "open" ? "filter-btn active" : "filter-btn" }, i18n.voteFilterOpen),
          button({ type: "submit", name: "filter", value: "closed", class: mode === "closed" ? "filter-btn active" : "filter-btn" }, i18n.voteFilterClosed),
          button({ type: "submit", name: "filter", value: "create", class: mode === "create" ? "create-button active" : "create-button" }, i18n.voteCreateButton)
        )
      )
    ),
    section(
      (mode === "edit" || mode === "create")
        ? div(
            { class: "vote-form" },
            form(
              { action: mode === "edit" ? `/votes/update/${encodeURIComponent(voteId)}` : "/votes/create", method: "POST" },
              input({ type: "hidden", name: "returnTo", value: listReturnTo }),
              h2(i18n.voteQuestionLabel),
              input({ type: "text", name: "question", id: "question", required: true, value: voteToEdit.question || "" }), br(), br(),
              label(i18n.voteDeadlineLabel), br(),
              input({
                type: "datetime-local",
                name: "deadline",
                id: "deadline",
                required: true,
                min: mode === "create" ? deadlineMin : undefined,
                value: deadlineValue
              }), br(), br(),
              label(i18n.voteTagsLabel), br(),
              input({ type: "text", name: "tags", id: "tags", value: editTags.join(", ") }), br(), br(),
              button({ type: "submit" }, mode === "edit" ? i18n.voteUpdateButton : i18n.voteCreateButton)
            )
          )
        : div(
            { class: "vote-list" },
            filtered.length > 0
              ? filtered.map((v) => renderVoteCard(v, voteOptions, firstRow, secondRow, mode, activeFilter))
              : p(i18n.novotes)
          ),
      (mode === "detail" && voteId) ? renderCommentsSection(voteId, comments, activeFilter) : null
    )
  );
};

