import { isDemo } from "@saasquatch/component-boilerplate";
import { withHooks } from "@saasquatch/stencil-hooks";
import { useEffect, useMemo, useReducer } from "@saasquatch/universal-hooks";
import { Component, h, Prop } from "@stencil/core";
import deepmerge from "deepmerge";
import { GenericTableView, } from "../../tables/GenericTableView";
import { useRequestRerender, useRerenderListener, } from "../../tables/re-render";
import { useChildElements } from "../../tables/useChildElements";
import mockReferralData from "./mockReferralData";
import { tryMethod, useReferralTable } from "./useReferralTable";
/**
 * @uiName Referral Table
 * @validParents ["sqm-portal-container","div","sqm-divided-layout","template","sqm-tab","sqb-program-section","sqb-conditional-section"]
 * @validChildren ["sqm-referral-table-column","sqm-referral-table-date-column","sqm-referral-table-rewards-column","sqm-referral-table-status-column","sqm-referral-table-user-column","sqm-empty"]
 * @exampleGroup Referrals
 * @slots [{"name":"", "title":"Table Row"},{"name":"empty", "title":"Empty"},{"name":"loading","title":"Loading"}]
 * @example Referral Table - <sqm-referral-table per-page="4" hidden-columns="2" more-label="Next" prev-label="Prev" sm-breakpoint="599" md-breakpoint="799" > <sqm-referral-table-user-column column-title="Customer" anonymous-user="Your Friend" deleted-user="Deleted User" ></sqm-referral-table-user-column> <sqm-referral-table-rewards-column column-title="Rewards" status-text="{status, select, AVAILABLE {Available} CANCELLED {Cancelled} PENDING {Pending} PENDING_REVIEW {Pending} PAYOUT_APPROVED {Payout Approved} PROCESSING {Payment Processing} PAYOUT_FAILED {Payout Failed} PAYOUT_CANCELLED {Payout Cancelled} PENDING_TAX_REVIEW {Pending} PENDING_NEW_TAX_FORM {Pending} PENDING_TAX_SUBMISSION {Pending} PENDING_PARTNER_CREATION {Pending} DENIED {Denied} EXPIRED {Expired} REDEEMED {Redeemed} other {Not available} }" status-long-text="{status, select, AVAILABLE {Reward expiring on} CANCELLED {Reward cancelled on} PENDING {Available on} PENDING_REVIEW {Pending since} PAYOUT_APPROVED {Processing until {scheduledPayoutDate}. Payout is then scheduled based on your settings.} PAYOUT_FAILED {Payout failed due to a fulfillment issue and is currently being retried.} PAYOUT_CANCELLED {If you think this is a mistake, contact our Support team.} PENDING_TAX_REVIEW {Awaiting tax form review} PENDING_NEW_TAX_FORM {Invalid tax form. Submit a new form to receive your rewards.} PROCESSING {Processing until {scheduledPayoutDate}. Payout is then scheduled based on your settings.} PENDING_TAX_SUBMISSION {Submit your tax documents to receive your rewards} PENDING_PARTNER_CREATION {Complete your tax and cash payout setup to receive your rewards} DENIED {Denied on} EXPIRED {Reward expired on} other {Not available} }" fuel-tank-text="Your code is" reward-received-text="Reward received on" expiring-text="Expiring in" pending-for-text="{status} for {date}" denied-help-text="Contact support if you think this is a mistake." ></sqm-referral-table-rewards-column> <sqm-referral-table-date-column column-title="Date converted" date-shown="dateConverted" ></sqm-referral-table-date-column> <sqm-referral-table-status-column column-title="Status" converted-status-text="Converted" in-progress-status-text="In Progress" pending-review-status-text="Pending" denied-status-text="Denied" pending-review-status-sub-text="Awaiting review" denied-status-sub-text="Detected self-referral" ></sqm-referral-table-status-column> <sqm-empty empty-state-image="https://res.cloudinary.com/saasquatch/image/upload/v1644000223/squatch-assets/empty_referral2.png" empty-state-header="View your referral details" empty-state-text="Refer a friend to view the status of your referrals and rewards earned" slot="empty" ></sqm-empty> </sqm-referral-table>
 */
export class ReferralTable {
  constructor() {
    /**
     * Number of referrals displayed per page
     *
     * @uiName Referrals per page
     */
    this.perPage = 4;
    /** @uiName Hide column labels */
    this.hideLabels = false;
    /** @uiName Previous button text  */
    this.prevLabel = "Prev";
    /** @uiName View More button text  */
    this.moreLabel = "Next";
    /**
     * Show referred by user in table
     *
     * @uiName Show referrer
     * @default
     */
    this.showReferrer = false;
    /**
     * Provide the column numbers (0 indexed) that should not be displayed in mobile views. Ex. 0,2,3
     *
     * @uiName Hidden mobile columns
     */
    this.hiddenColumns = "0";
    /** @uiName Mobile breakpoint  */
    this.smBreakpoint = 599;
    /** @uiName Tablet breakpoint  */
    this.mdBreakpoint = 799;
    withHooks(this);
  }
  disconnectedCallback() { }
  render() {
    const empty = h(EmptySlot, null);
    const loading = h(LoadingSlot, null);
    const { states, data, callbacks, elements } = isDemo()
      ? useReferralTableDemo(this, empty, loading)
      : useReferralTable(this, empty, loading);
    useRequestRerender([this.showReferrer, this.perPage]);
    return (h(GenericTableView, { states: states, data: data, callbacks: callbacks, elements: elements }));
  }
  static get is() { return "sqm-referral-table"; }
  static get encapsulation() { return "shadow"; }
  static get properties() { return {
    "programId": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [{
            "text": "Program",
            "name": "uiName"
          }, {
            "text": "programSelector",
            "name": "uiWidget"
          }],
        "text": "Filters to only show referrals in this program. Will default to filtering by the program context where\nthis table lives. If no program ID is set or provided by context, then shows all referrals from all programs.\nIf program ID is \"classic\", shows classic-only referrals"
      },
      "attribute": "program-id",
      "reflect": false
    },
    "perPage": {
      "type": "number",
      "mutable": false,
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [{
            "text": "Referrals per page",
            "name": "uiName"
          }],
        "text": "Number of referrals displayed per page"
      },
      "attribute": "per-page",
      "reflect": false,
      "defaultValue": "4"
    },
    "hideLabels": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [{
            "text": "Hide column labels",
            "name": "uiName"
          }],
        "text": ""
      },
      "attribute": "hide-labels",
      "reflect": false,
      "defaultValue": "false"
    },
    "prevLabel": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [{
            "text": "Previous button text",
            "name": "uiName"
          }],
        "text": ""
      },
      "attribute": "prev-label",
      "reflect": false,
      "defaultValue": "\"Prev\""
    },
    "moreLabel": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [{
            "text": "View More button text",
            "name": "uiName"
          }],
        "text": ""
      },
      "attribute": "more-label",
      "reflect": false,
      "defaultValue": "\"Next\""
    },
    "showReferrer": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [{
            "text": "Show referrer",
            "name": "uiName"
          }, {
            "text": undefined,
            "name": "default"
          }],
        "text": "Show referred by user in table"
      },
      "attribute": "show-referrer",
      "reflect": false,
      "defaultValue": "false"
    },
    "hiddenColumns": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [{
            "text": "Hidden mobile columns",
            "name": "uiName"
          }],
        "text": "Provide the column numbers (0 indexed) that should not be displayed in mobile views. Ex. 0,2,3"
      },
      "attribute": "hidden-columns",
      "reflect": false,
      "defaultValue": "\"0\""
    },
    "smBreakpoint": {
      "type": "number",
      "mutable": false,
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [{
            "text": "Mobile breakpoint",
            "name": "uiName"
          }],
        "text": ""
      },
      "attribute": "sm-breakpoint",
      "reflect": false,
      "defaultValue": "599"
    },
    "mdBreakpoint": {
      "type": "number",
      "mutable": false,
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [{
            "text": "Tablet breakpoint",
            "name": "uiName"
          }],
        "text": ""
      },
      "attribute": "md-breakpoint",
      "reflect": false,
      "defaultValue": "799"
    },
    "demoData": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "DemoData<GenericTableViewProps> & {\n    mockData?: { data: Referral[] };\n  }",
        "resolved": "Partial<Pick<GenericTableViewProps, \"states\" | \"data\" | \"elements\">> & { mockData?: { data: Referral[]; }; }",
        "references": {
          "DemoData": {
            "location": "import",
            "path": "../../global/demo"
          },
          "GenericTableViewProps": {
            "location": "import",
            "path": "../../tables/GenericTableView"
          },
          "Referral": {
            "location": "import",
            "path": "../../saasquatch"
          }
        }
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [{
            "text": undefined,
            "name": "undocumented"
          }, {
            "text": "object",
            "name": "uiType"
          }],
        "text": ""
      }
    }
  }; }
}
function EmptySlot() {
  return (h("slot", { name: "empty" },
    h("sqm-empty", { "empty-state-image": "https://res.cloudinary.com/saasquatch/image/upload/v1644000223/squatch-assets/empty_referral2.png", "empty-state-header": "View your referral details", "empty-state-text": "Refer a friend to view the status of your referrals and rewards earned" })));
}
function LoadingSlot() {
  return (h("slot", { name: "loading" },
    h(LoadingRow, null),
    h(LoadingRow, null),
    h(LoadingRow, null),
    h(LoadingRow, null)));
}
function LoadingRow() {
  return (h("sqm-table-row", null,
    h("sqm-table-cell", { colspan: 5 },
      h("sqm-skeleton", null))));
}
function useReferralTableDemo(props, emptyElement, loadingElement) {
  const [content, setContent] = useReducer((state, next) => ({
    ...state,
    ...next,
  }), {
    columns: [],
    rows: [],
    loading: false,
    page: 0,
  });
  const tick = useRerenderListener();
  const mockData = useMemo(() => { var _a; return ((_a = props.demoData) === null || _a === void 0 ? void 0 : _a.mockData) || mockReferralData(props.perPage); }, [props.perPage]);
  const components = useChildElements();
  async function getComponentData(components) {
    var _a;
    let componentData;
    //@ts-ignore
    const referrerData = mockData === null || mockData === void 0 ? void 0 : mockData.referredByReferral;
    const showReferrerRow = props.showReferrer &&
      //@ts-ignore
      !!((_a = mockData === null || mockData === void 0 ? void 0 : mockData.referredByReferral) === null || _a === void 0 ? void 0 : _a.dateReferralStarted);
    if (showReferrerRow) {
      componentData = mockData.data.slice(0, props.perPage - 1);
    }
    else {
      componentData = mockData.data.slice(0, props.perPage);
    }
    // filter out loading and empty states from columns array
    const columnComponents = components.filter((component) => {
      var _a, _b;
      return component.slot !== "loading" &&
        component.slot !== "empty" &&
        ((_a = component === null || component === void 0 ? void 0 : component.firstElementChild) === null || _a === void 0 ? void 0 : _a.getAttribute("slot")) !== "loading" &&
        ((_b = component === null || component === void 0 ? void 0 : component.firstElementChild) === null || _b === void 0 ? void 0 : _b.getAttribute("slot")) !== "empty";
    });
    // get the column titles (renderLabel is asynchronous)
    const columnsPromise = columnComponents === null || columnComponents === void 0 ? void 0 : columnComponents.map(async (c, idx) => {
      var _a;
      const slot = (_a = c === null || c === void 0 ? void 0 : c.firstElementChild) === null || _a === void 0 ? void 0 : _a.getAttribute("slot");
      // Custom plop targets
      if (c.tagName === "RAISINS-PLOP-TARGET" &&
        slot !== "loading" &&
        slot !== "empty") {
        c.setAttribute("slot", "column-" + idx);
        c.style.position = "absolute";
        // Replace add text with a simple + button
        const plopTarget = c.firstElementChild.childNodes[1];
        plopTarget.innerHTML = "＋";
        plopTarget.style.lineHeight = "20px";
        return tryMethod(c, () => c.renderLabel(idx));
      }
      return tryMethod(c, () => c.renderLabel());
    });
    // show the referrer row before any other rows (renderReferrerCell is asynchronous)
    let referrerRow;
    if (showReferrerRow) {
      const referrerPromise = columnComponents === null || columnComponents === void 0 ? void 0 : columnComponents.map(async (c) => tryMethod(c, function renderCell() {
        return c.renderCell(referrerData, c);
      }));
      referrerRow = await Promise.all(referrerPromise);
    }
    // get the column cells (renderCell is asynchronous)
    const cellsPromise = componentData === null || componentData === void 0 ? void 0 : componentData.map(async (r) => {
      const cellPromise = columnComponents === null || columnComponents === void 0 ? void 0 : columnComponents.map(async (c) => tryMethod(c, () => c.renderCell(r, undefined)));
      const cells = (await Promise.all(cellPromise));
      return cells;
    });
    const rows = cellsPromise &&
      [referrerRow, ...(await Promise.all(cellsPromise))].filter((value) => value);
    setContent({ rows });
    const columns = columnsPromise && (await Promise.all(columnsPromise));
    // Set the content to render and finish loading components
    setContent({ columns, loading: false, page: 0 });
  }
  useEffect(() => {
    setContent({ loading: true });
    (mockData === null || mockData === void 0 ? void 0 : mockData.data) && getComponentData(components);
  }, [mockData === null || mockData === void 0 ? void 0 : mockData.data, components, tick]);
  const demoProps = deepmerge({
    states: {
      hasPrev: false,
      hasNext: false,
      loading: false,
      show: "rows",
    },
    callbacks: {
      prevPage: () => console.log("Prev"),
      nextPage: () => console.log("Next"),
    },
    data: {
      textOverrides: {
        showLabels: !props.hideLabels,
        prevLabel: props.prevLabel,
        moreLabel: props.moreLabel,
      },
      hiddenColumns: props.hiddenColumns,
      referralData: [],
      mdBreakpoint: 799,
      smBreakpoint: 599,
    },
    elements: {
      columns: content.columns,
      rows: content.rows,
      emptyElement,
      loadingElement,
    },
  }, props.demoData || {}, { arrayMerge: (_, a) => a });
  return demoProps;
}
