/**
 * The per-post restriction configurator form.
 *
 * Field-for-field the same configuration as the "Restricted Content" Gutenberg
 * block (mode, access rules, plan feature), reusing the very same REST-backed
 * pickers, plus the denial behaviour a whole page needs: replace the content
 * with a message, or redirect the visitor somewhere else.
 */
import {
  Notice,
  SelectControl,
  TextControl,
  ToggleControl,
  __experimentalNumberControl as NumberControl,
} from "@wordpress/components";
import { __ } from "@wordpress/i18n";
import RichTextField from "@libs/form-builder/fields/RichText";

import {
  AsyncIdCombobox,
  AsyncTokenSelect,
  FeatureCombobox,
  StaticTokenSelect,
} from "@libs/access-controls";

import {
  DEFAULT_MESSAGE,
  ROLE_OPTIONS,
  STATUS_OPTIONS,
  warningFor,
} from "./config";

function RestrictionSection({ title, className = "", children }) {
  const classes = ["arraysubs-restriction-fields__section", className]
    .filter(Boolean)
    .join(" ");

  return (
    <section className={classes}>
      <h3 className="arraysubs-restriction-fields__section-title">{title}</h3>
      <div className="arraysubs-restriction-fields__section-content">
        {children}
      </div>
    </section>
  );
}

function DeniedSection({ config, set, update }) {
  return (
    <RestrictionSection
      title={__("When Access Is Denied", "arraysubs")}
      className="arraysubs-restriction-fields__section--denied"
    >
      <SelectControl
        __next40pxDefaultSize
        __nextHasNoMarginBottom
        label={__("What Should Happen", "arraysubs")}
        value={config.deniedAction}
        help={
          config.deniedAction === "redirect"
            ? __(
                "The visitor never sees this page — they are sent straight to the destination below.",
                "arraysubs",
              )
            : __(
                "The visitor stays on this page, but the whole content is replaced with the message below.",
                "arraysubs",
              )
        }
        options={[
          {
            label: __("Show a message instead of the content", "arraysubs"),
            value: "message",
          },
          {
            label: __("Redirect to another page", "arraysubs"),
            value: "redirect",
          },
        ]}
        onChange={set("deniedAction")}
      />

      {config.deniedAction === "message" && (
        <RichTextField
          standalone
          height={180}
          toolbar="bold italic | bullist numlist | link unlink | removeformat"
          label={__("Restricted Message", "arraysubs")}
          help={__(
            "Replaces the entire content for visitors who fail the rules. Leave empty to use the default message from Content Gate. You can use {site_name}, {login_link} and {pricing_link}.",
            "arraysubs",
          )}
          value={config.message}
          placeholder={DEFAULT_MESSAGE}
          onChange={set("message")}
        />
      )}

      {config.deniedAction === "redirect" && (
        <>
          <SelectControl
            __next40pxDefaultSize
            __nextHasNoMarginBottom
            label={__("Redirect Destination", "arraysubs")}
            value={config.redirectType}
            options={[
              {
                label: __("A page on this site", "arraysubs"),
                value: "page",
              },
              {
                label: __("A custom URL", "arraysubs"),
                value: "url",
              },
            ]}
            onChange={set("redirectType")}
          />

          {config.redirectType === "page" && (
            <AsyncIdCombobox
              label={__("Page", "arraysubs")}
              help={__(
                "Search any published page and pick where denied visitors land.",
                "arraysubs",
              )}
              type="posts"
              query={{ post_type: "page" }}
              value={config.redirectPageId}
              onChange={(id, label) =>
                update({
                  redirectPageId: id,
                  redirectPageLabel: label,
                })
              }
              onResolveLabel={(label) => {
                if (label && label !== config.redirectPageLabel) {
                  update({
                    redirectPageLabel: label,
                  });
                }
              }}
            />
          )}

          {config.redirectType === "url" && (
            <TextControl
              __next40pxDefaultSize
              __nextHasNoMarginBottom
              type="url"
              label={__("Redirect URL", "arraysubs")}
              help={__(
                "Full URL including https://. Internal and external addresses both work.",
                "arraysubs",
              )}
              value={config.redirectUrl}
              placeholder="https://example.com/pricing"
              onChange={set("redirectUrl")}
            />
          )}
        </>
      )}

      <ToggleControl
        __nextHasNoMarginBottom
        label={__("Only login is required—nothing else", "arraysubs")}
        help={__(
          "Any logged-in user can view this content. All other conditions are skipped; guests are denied.",
          "arraysubs",
        )}
        checked={!!config.loginRequired}
        onChange={set("loginRequired")}
      />

      <ToggleControl
        __nextHasNoMarginBottom
        label={__("Always Show To Admins", "arraysubs")}
        help={__(
          "Administrators bypass this restriction so a rule can never lock you out.",
          "arraysubs",
        )}
        checked={!!config.showToAdmins}
        onChange={set("showToAdmins")}
      />
    </RestrictionSection>
  );
}

export default function RestrictionFields({ config, update }) {
  const set = (key) => (value) => update({ [key]: value });

  const isRestrict = config.mode === "restrict";
  const isVisibility = config.mode === "visibility";
  const showFeatureAmount =
    isRestrict &&
    config.feature &&
    ["min_total", "min_single", "custom"].includes(config.featureMatch);
  const showFeatureCustom =
    isRestrict && config.feature && config.featureMatch === "custom";
  const warning = warningFor(config);

  return (
    <div className="arraysubs-restriction-fields">
      <ToggleControl
        __nextHasNoMarginBottom
        label={__("Restrict access to this content", "arraysubs")}
        help={__(
          "When off, the settings below are ignored and Members Access rules apply.",
          "arraysubs",
        )}
        checked={!!config.enabled}
        onChange={set("enabled")}
      />

      {!!warning && (
        <Notice status="warning" isDismissible={false}>
          {warning}
        </Notice>
      )}

      {!!config.enabled && (
        <Notice status="info" isDismissible={false}>
          {__(
            "This restriction has the highest priority for this content. While active, it overrides Shop Access, URL, Post Types, and Comments rules, including their denied actions and archive behavior. URL and Post Types overlaps are listed under Members Access → Access-Rule Conflicts.",
            "arraysubs",
          )}
        </Notice>
      )}

      {!!config.enabled && (
        <>
          <RestrictionSection
            title={__("Restriction Type", "arraysubs")}
            className="arraysubs-restriction-fields__section--restriction-type"
          >
            <SelectControl
              __next40pxDefaultSize
              __nextHasNoMarginBottom
              hideLabelFromVision
              label={__("Restriction Type", "arraysubs")}
              value={config.mode}
              options={[
                {
                  label: __(
                    "Subscription / Role / Purchase (restrict)",
                    "arraysubs",
                  ),
                  value: "restrict",
                },
                {
                  label: __("Login state (visibility)", "arraysubs"),
                  value: "visibility",
                },
              ]}
              onChange={set("mode")}
            />
          </RestrictionSection>

          <DeniedSection config={config} set={set} update={update} />

          {isVisibility && (
            <RestrictionSection
              title={__("Visibility", "arraysubs")}
              className="arraysubs-restriction-fields__section--visibility"
            >
              <SelectControl
                __next40pxDefaultSize
                __nextHasNoMarginBottom
                label={__("Show To", "arraysubs")}
                value={config.visShow}
                options={[
                  {
                    label: __("Logged-in users", "arraysubs"),
                    value: "logged_in",
                  },
                  {
                    label: __("Logged-out users", "arraysubs"),
                    value: "logged_out",
                  },
                ]}
                onChange={set("visShow")}
              />
            </RestrictionSection>
          )}

          {isRestrict && (
            <RestrictionSection
              className="arraysubs-restriction-fields__section--access-rules"
              title={__("Access Rules", "arraysubs")}
            >
              <StaticTokenSelect
                label={__("Subscription Status", "arraysubs")}
                options={STATUS_OPTIONS}
                values={config.status}
                onChange={set("status")}
              />

              <AsyncTokenSelect
                label={__("Active Subscription To Products", "arraysubs")}
                type="products"
                query={{ product_type: "subscription" }}
                ids={config.products}
                onChangeIds={set("products")}
              />

              <AsyncTokenSelect
                label={__("Active Subscription To Variations", "arraysubs")}
                type="variations"
                query={{ product_type: "subscription" }}
                ids={config.variations}
                onChangeIds={set("variations")}
              />

              <AsyncTokenSelect
                label={__("Purchased Products (any purchase)", "arraysubs")}
                type="products"
                ids={config.purchased}
                onChangeIds={set("purchased")}
              />

              <StaticTokenSelect
                label={__("User Roles", "arraysubs")}
                options={ROLE_OPTIONS}
                values={config.roles}
                onChange={set("roles")}
              />

              <NumberControl
                __next40pxDefaultSize
                label={__("Minimum Lifetime Spend", "arraysubs")}
                min={0}
                step={0.01}
                value={config.lifetimeSpent}
                onChange={(v) =>
                  update({
                    lifetimeSpent: v == null ? "" : String(v),
                  })
                }
              />

              <SelectControl
                __next40pxDefaultSize
                __nextHasNoMarginBottom
                label={__("Match Logic", "arraysubs")}
                value={config.condition}
                options={[
                  {
                    label: __("Match ALL of the above (AND)", "arraysubs"),
                    value: "and",
                  },
                  {
                    label: __("Match ANY of the above (OR)", "arraysubs"),
                    value: "or",
                  },
                ]}
                onChange={set("condition")}
              />
            </RestrictionSection>
          )}

          {isRestrict && (
            <RestrictionSection
              title={__("Plan Feature (Pro)", "arraysubs")}
              className="arraysubs-restriction-fields__section--plan-feature"
            >
              <p className="arraysubs-control-note">
                {__(
                  "Gate by a feature defined on your subscription products (Product → Features, requires ArraySubs Pro). Pick a feature, then choose how to check it. Leave empty to not use a feature rule.",
                  "arraysubs",
                )}
              </p>

              <FeatureCombobox
                label={__("Feature", "arraysubs")}
                help={__(
                  "The feature name, exactly as defined on the product.",
                  "arraysubs",
                )}
                value={config.feature}
                onChange={set("feature")}
              />

              {!!config.feature && (
                <SelectControl
                  __next40pxDefaultSize
                  __nextHasNoMarginBottom
                  label={__("How To Check It", "arraysubs")}
                  value={config.featureMatch}
                  help={__(
                    'On/off (toggle) features: use "Has the feature". Numeric features (e.g. seats, API calls): use one of the "at least" options.',
                    "arraysubs",
                  )}
                  options={[
                    {
                      label: __(
                        "Has the feature (on/off features)",
                        "arraysubs",
                      ),
                      value: "has",
                    },
                    {
                      label: __(
                        "Combined amount across their plans is at least…",
                        "arraysubs",
                      ),
                      value: "min_total",
                    },
                    {
                      label: __(
                        "At least one plan provides at least…",
                        "arraysubs",
                      ),
                      value: "min_single",
                    },
                    {
                      label: __("Custom comparison (advanced)", "arraysubs"),
                      value: "custom",
                    },
                  ]}
                  onChange={set("featureMatch")}
                />
              )}

              {showFeatureAmount && (
                <NumberControl
                  __next40pxDefaultSize
                  label={__("Required Amount", "arraysubs")}
                  min={0}
                  value={config.featureValue}
                  help={__("The number the feature must reach.", "arraysubs")}
                  onChange={(v) =>
                    update({
                      featureValue: v == null ? "" : String(v),
                    })
                  }
                />
              )}

              {showFeatureCustom && (
                <SelectControl
                  __next40pxDefaultSize
                  __nextHasNoMarginBottom
                  label={__("Comparison", "arraysubs")}
                  value={config.featureOp}
                  options={[
                    { label: __("At least (>=)", "arraysubs"), value: ">=" },
                    { label: __("More than (>)", "arraysubs"), value: ">" },
                    { label: __("Exactly (=)", "arraysubs"), value: "=" },
                    { label: __("Not equal (!=)", "arraysubs"), value: "!=" },
                    { label: __("Less than (<)", "arraysubs"), value: "<" },
                    { label: __("At most (<=)", "arraysubs"), value: "<=" },
                  ]}
                  onChange={set("featureOp")}
                />
              )}

              {showFeatureCustom && (
                <SelectControl
                  __next40pxDefaultSize
                  __nextHasNoMarginBottom
                  label={__("Combine Multiple Plans By", "arraysubs")}
                  value={config.aggregation}
                  help={__(
                    'For presence (on/off) checks use the "Has the feature" mode instead.',
                    "arraysubs",
                  )}
                  options={[
                    {
                      label: __("Sum — add values across plans", "arraysubs"),
                      value: "sum",
                    },
                    {
                      label: __("Max — highest single plan", "arraysubs"),
                      value: "max",
                    },
                  ]}
                  onChange={set("aggregation")}
                />
              )}
            </RestrictionSection>
          )}
        </>
      )}
    </div>
  );
}
