/** Shared access rule layout for post restrictions and Restricted Content blocks. */
import { useEffect } from "@wordpress/element";
import {
  SelectControl,
  ToggleControl,
  __experimentalNumberControl as NumberControl,
} from "@wordpress/components";
import { __ } from "@wordpress/i18n";
import {
  AsyncTokenSelect,
  FeatureCombobox,
  StaticTokenSelect,
} from "@libs/access-controls";
import { normalizeConditionLogic } from "@/components/RestrictionRuleBuilder/conditionLogic";
import { hasAccessConditions, withRequiredLogin } from "./accessConditions";
import "./access-rule-sections.scss";

export function AccessSection({ title, className = "", children }) {
  return (
    <section className={`arraysubs-access-section ${className}`}>
      <h3 className="arraysubs-access-section__title">{title}</h3>
      <div className="arraysubs-access-section__content">{children}</div>
    </section>
  );
}

function PlanFeatureFields({ config, set, update }) {
  const showAmount =
    !!config.feature &&
    ["min_total", "min_single", "custom"].includes(config.featureMatch);
  const showCustom = !!config.feature && config.featureMatch === "custom";

  return (
    <div className="arraysubs-access-conditions__feature">
      <FeatureCombobox
        label={__("Plan Feature (Pro)", "arraysubs")}
        help={__(
          "Choose a feature defined on your subscription products. Requires ArraySubs Pro.",
          "arraysubs",
        )}
        value={config.feature}
        onChange={set("feature")}
      />
      {!!config.feature && (
        <div className="arraysubs-access-conditions__feature-options">
          <SelectControl
            __next40pxDefaultSize
            __nextHasNoMarginBottom
            label={__("How To Check It", "arraysubs")}
            value={config.featureMatch}
            help={__(
              'For an on/off feature, choose "Has the feature". For an amount, choose one of the comparison options.',
              "arraysubs",
            )}
            options={[
              { label: __("Has the feature", "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")}
          />
          {showAmount && (
            <NumberControl
              __next40pxDefaultSize
              label={__("Required Amount", "arraysubs")}
              min={0}
              value={config.featureValue}
              help={__("The number the feature must reach.", "arraysubs")}
              onChange={(value) => update({ featureValue: value == null ? "" : String(value) })}
            />
          )}
          {showCustom && (
            <>
              <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")}
              />
              <SelectControl
                __next40pxDefaultSize
                __nextHasNoMarginBottom
                label={__("Combine Multiple Plans By", "arraysubs")}
                value={config.aggregation}
                options={[
                  { label: __("Sum — add values across plans", "arraysubs"), value: "sum" },
                  { label: __("Max — highest single plan", "arraysubs"), value: "max" },
                ]}
                onChange={set("aggregation")}
              />
            </>
          )}
        </div>
      )}
    </div>
  );
}

export default function AccessRuleSections({
  config,
  update,
  statusOptions = [],
  roleOptions = [],
  Section = AccessSection,
  includeAdmin = true,
}) {
  const conditionsApplied = hasAccessConditions(config);
  const updateRules = (patch) => {
    const next = withRequiredLogin({ ...config, ...patch });
    update({ ...patch, loginRequired: next.loginRequired });
  };
  const set = (key) => (value) => updateRules({ [key]: value });

  useEffect(() => {
    if (conditionsApplied && !config.loginRequired) {
      update({ loginRequired: true });
    }
  }, [conditionsApplied, config.loginRequired, update]);

  return (
    <>
      <Section
        title={__("Who can access it", "arraysubs")}
        className="arraysubs-access-conditions"
        initialOpen={true}
      >
        <ToggleControl
          __nextHasNoMarginBottom
          label={__("Logged-in users", "arraysubs")}
          help={conditionsApplied
            ? __("Required while any condition below is set. Login is checked separately from Match Logic.", "arraysubs")
            : __("When enabled on its own, any logged-in user can access this content.", "arraysubs")}
          checked={conditionsApplied || !!config.loginRequired}
          disabled={conditionsApplied}
          onChange={set("loginRequired")}
        />
        <hr className="arraysubs-access-conditions__separator" />
        <p className="arraysubs-access-conditions__help">
          {__("Set the conditions logged-in users must meet. Leave a field empty to skip it.", "arraysubs")}
        </p>
        <div className="arraysubs-access-conditions__fields">
          <StaticTokenSelect
            label={__("Subscription Status", "arraysubs")}
            options={statusOptions}
            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={roleOptions}
            values={config.roles}
            onChange={set("roles")}
          />
          <NumberControl
            __next40pxDefaultSize
            label={__("Minimum Lifetime Spend", "arraysubs")}
            min={0}
            step={0.01}
            value={config.lifetimeSpent}
            onChange={(value) => updateRules({ lifetimeSpent: value == null ? "" : String(value) })}
          />
          <PlanFeatureFields config={config} set={set} update={updateRules} />
        </div>
      </Section>
      <Section title={__("Match Logic", "arraysubs")} initialOpen={true}>
        <SelectControl
          __next40pxDefaultSize
          __nextHasNoMarginBottom
          label={__("Match Logic", "arraysubs")}
          hideLabelFromVision
          value={normalizeConditionLogic(config.condition)}
          options={[
            { label: __("Match ALL conditions (AND)", "arraysubs"), value: "and" },
            { label: __("Match ANY condition (OR)", "arraysubs"), value: "or" },
          ]}
          help={__("Applies to the conditions above. Users must still be logged in.", "arraysubs")}
          onChange={set("condition")}
        />
      </Section>
      {includeAdmin && <AdminAccessSection config={config} update={update} Section={Section} />}
    </>
  );
}


export function AdminAccessSection({ config, update, Section = AccessSection }) {
  return (
    <Section title={__("Always Show To Admins", "arraysubs")} initialOpen={true}>
      <ToggleControl
        __nextHasNoMarginBottom
        label={__("Always Show To Admins", "arraysubs")}
        help={__("Administrators can access this content without meeting any other condition.", "arraysubs")}
        checked={!!config.showToAdmins}
        onChange={(value) => update({ showToAdmins: value })}
      />
    </Section>
  );
}
