import React, { useState, useEffect, useCallback } from "react";
import { __ } from "@wordpress/i18n";
import Form from "rc-field-form";
import FormBuilder from "@libs/form-builder";
import { Skeleton } from "@libs/skeleton";
import { ToastContainer } from "@libs/toast";
import { useToast } from "@libs/toast/useToast";
import DefaultPageLayout from "@/components/DefaultPageLayout";
import {
  dotToNested,
  nestedToDot,
  fetchSettings,
  saveSettings,
} from "./settingsHelpers";
import { buildUrl } from "@libs/url";

/**
 * Check whether a boot class (feature provider) is loaded.
 *
 * @param {string} fragment - A substring to match against the loaded PHP class names.
 * @returns {boolean}
 */
const isFeatureLoaded = (fragment) => {
  const classes = window.arraySubs?.liveBootClasses || [];
  return classes.some((cls) => cls.includes(fragment));
};

/**
 * Build the form structure for Toolkit settings.
 *
 * Receives roles as a parameter so the MultiSelect data
 * can be populated after the async fetch.
 *
 * @param {Array} roleOptions - Array of { value, label } for WP roles.
 * @returns {Array} FormBuilder formItems structure.
 */
const getFormStructure = (roleOptions) => [
  // Admin Bar
  {
    field: "Card",
    children: [
      {
        field: "Title",
        heading: 3,
        text: __("Admin Bar", "arraysubs"),
        subText: __(
          "Control the WordPress admin bar visibility on the frontend",
          "arraysubs",
        ),
      },
      {
        field: "Switch",
        name: "toolkit.hide_admin_bar",
        label: __("Hide admin bar for non-admin users", "arraysubs"),
      },
      {
        field: "Alert",
        type: "info",
        message: __(
          "When enabled, the WordPress admin bar will be hidden on the frontend for all users who are not administrators or do not have an allowed role. Administrators always see the admin bar.",
          "arraysubs",
        ),
      },
      {
        field: "Alert",
        type: "info",
        message: __(
          "Flow: members and customers browse the frontend without the WordPress toolbar, while administrators and allowed staff still keep their normal admin shortcuts. This only affects the frontend view and does not change backend capabilities by itself.",
          "arraysubs",
        ),
      },
    ],
  },

  // WP-Admin Access
  {
    field: "Card",
    children: [
      {
        field: "Title",
        heading: 3,
        text: __("Admin Dashboard Access", "arraysubs"),
        subText: __(
          "Restrict access to the WordPress admin dashboard for non-admin users",
          "arraysubs",
        ),
      },
      {
        field: "Switch",
        name: "toolkit.restrict_wp_admin",
        label: __("Restrict wp-admin access", "arraysubs"),
      },
      {
        field: "Select",
        name: "toolkit.wp_admin_redirect",
        label: __("Redirect unauthorized users to", "arraysubs"),
        data: [
          {
            label: __("WooCommerce My Account page", "arraysubs"),
            value: "my_account",
          },
          {
            label: __("404 Not Found page", "arraysubs"),
            value: "not_found",
          },
        ],
        showWhen: {
          field: "toolkit.restrict_wp_admin",
          operator: "=",
          value: true,
        },
      },
      {
        field: "MultiSelect",
        name: "toolkit.allowed_roles",
        label: __("Allowed roles", "arraysubs"),
        data: roleOptions,
        placeholder: __("Select roles that retain admin access…", "arraysubs"),
        showWhen: {
          field: "toolkit.restrict_wp_admin",
          operator: "=",
          value: true,
        },
      },
      {
        field: "Alert",
        type: "info",
        message: __(
          "Users with the selected roles will still have access to the WordPress admin dashboard. Administrators always have access regardless of this setting. AJAX, REST API, WP-Cron, and other infrastructure requests are never blocked.",
          "arraysubs",
        ),
        showWhen: {
          field: "toolkit.restrict_wp_admin",
          operator: "=",
          value: true,
        },
      },
      {
        field: "Alert",
        type: "warning",
        message: __(
          "Flow: after saving, members who try to open /wp-admin will be redirected to the destination you choose here. Administrators are always allowed, and any selected staff roles keep normal backend access. Logged-out visitors can still reach the normal WordPress authentication flow when admin access requires login.",
          "arraysubs",
        ),
        showWhen: {
          field: "toolkit.restrict_wp_admin",
          operator: "=",
          value: true,
        },
      },
    ],
  },

  // WP Login Page
  {
    field: "Card",
    children: [
      {
        field: "Title",
        heading: 3,
        text: __("WordPress Login Page", "arraysubs"),
        subText: __(
          "Hide the default WordPress login page and funnel logins through WooCommerce",
          "arraysubs",
        ),
      },
      {
        field: "Switch",
        name: "toolkit.hide_wp_login",
        label: __("Hide WordPress login page", "arraysubs"),
      },
      {
        field: "Select",
        name: "toolkit.wp_login_redirect",
        label: __("Redirect login page to", "arraysubs"),
        data: [
          {
            label: __("WooCommerce My Account page", "arraysubs"),
            value: "my_account",
          },
          {
            label: __("404 Not Found page", "arraysubs"),
            value: "not_found",
          },
        ],
        showWhen: {
          field: "toolkit.hide_wp_login",
          operator: "=",
          value: true,
        },
      },
      {
        field: "Alert",
        type: "warning",
        message: __(
          "Password reset links, email verification callbacks, and logout requests will continue to work even when the login page is hidden. Administrators can always access the login page when logged in.",
          "arraysubs",
        ),
        showWhen: {
          field: "toolkit.hide_wp_login",
          operator: "=",
          value: true,
        },
      },
      {
        field: "Alert",
        type: "info",
        message: __(
          "When this is enabled, the default /wp-login.php page will redirect visitors to the selected target. WooCommerce My Account should be configured to handle login and registration. This makes your membership site feel like a true frontend experience.",
          "arraysubs",
        ),
        showWhen: {
          field: "toolkit.hide_wp_login",
          operator: "=",
          value: true,
        },
      },
      {
        field: "Alert",
        type: "info",
        message: __(
          "Flow: customer-facing login and sign-up links now resolve to the WooCommerce My Account page instead of wp-login.php. That includes third-party plugins or themes that call the standard WordPress login or registration URL helpers. Admin-targeted login flows still keep the WordPress admin login path when needed.",
          "arraysubs",
        ),
        showWhen: {
          field: "toolkit.hide_wp_login",
          operator: "=",
          value: true,
        },
      },
      {
        field: "Alert",
        type: "warning",
        message: __(
          "Before enabling this on a live site, confirm that WooCommerce account registration is configured the way you want and that your My Account page is publicly reachable. If registration is disabled in WooCommerce, visitors will still land on My Account but only the login form will be available.",
          "arraysubs",
        ),
        showWhen: {
          field: "toolkit.hide_wp_login",
          operator: "=",
          value: true,
        },
      },
    ],
  },

  // Login as User
  {
    field: "Card",
    children: [
      {
        field: "Title",
        heading: 3,
        text: __("Login as User", "arraysubs"),
        subText: __(
          "Allow administrators to log in as any non-admin user for troubleshooting and support",
          "arraysubs",
        ),
      },
      {
        field: "Switch",
        name: "toolkit.login_as_user",
        label: __("Enable Login as User", "arraysubs"),
      },
      {
        field: "Alert",
        type: "info",
        message: __(
          "When enabled, administrators can impersonate non-admin users from the Users list, user profile, WooCommerce order pages, and subscription detail screens. A notification bar is shown while impersonating.",
          "arraysubs",
        ),
      },
    ],
  },

  // Multi-Login Prevention
  ...(isFeatureLoaded("MultiLoginPrevention")
    ? [
        {
          field: "Card",
          children: [
            {
              field: "Title",
              heading: 3,
              text: __("Multi-Login Prevention", "arraysubs"),
              subText: __(
                "Limit the number of concurrent login sessions per user to prevent credential sharing",
                "arraysubs",
              ),
            },
            {
              field: "Switch",
              name: "toolkit.multi_login_prevention",
              label: __("Enable Multi-Login Prevention", "arraysubs"),
            },
            {
              field: "Number",
              name: "toolkit.multi_login_max_sessions",
              label: __("Default max sessions per user", "arraysubs"),
              min: 1,
              step: 1,
              showWhen: {
                field: "toolkit.multi_login_prevention",
                operator: "=",
                value: true,
              },
            },
            {
              field: "Alert",
              type: "info",
              message: __(
                "This is the global default. Users who match a Login Limit rule in Members Access will use that rule's limit instead. When a user exceeds the session limit, the oldest sessions are automatically destroyed.",
                "arraysubs",
              ),
              showWhen: {
                field: "toolkit.multi_login_prevention",
                operator: "=",
                value: true,
              },
            },
            {
              field: "Switch",
              name: "toolkit.multi_login_include_admins",
              label: __("Apply to administrators", "arraysubs"),
              showWhen: {
                field: "toolkit.multi_login_prevention",
                operator: "=",
                value: true,
              },
            },
            {
              field: "Alert",
              type: "warning",
              message: __(
                "By default, administrators are exempt from session limits. Enable this if you also want to enforce limits for administrator accounts.",
                "arraysubs",
              ),
              showWhen: {
                field: "toolkit.multi_login_prevention",
                operator: "=",
                value: true,
              },
            },
            {
              field: "Alert",
              type: "info",
              message: __(
                "Flow: when a customer logs in and already has the maximum number of sessions, the oldest session is automatically terminated. The current login always succeeds. Impersonated sessions (Login as User) are never counted toward the limit.",
                "arraysubs",
              ),
              showWhen: {
                field: "toolkit.multi_login_prevention",
                operator: "=",
                value: true,
              },
            },
            {
              field: "Alert",
              type: "info",
              message: __(
                "For per-subscription or per-role session limits, configure Login Limit Rules in Members Access → Login Limit.",
                "arraysubs",
              ),
              showWhen: {
                field: "toolkit.multi_login_prevention",
                operator: "=",
                value: true,
              },
            },
          ],
        },
      ]
    : []),
];

const ToolkitSettings = () => {
  const [form] = Form.useForm();
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [formData, setFormData] = useState({});
  const [roleOptions, setRoleOptions] = useState([]);
  const { toasts, showToast, removeToast } = useToast();
  const { env } = window.arraySubs || {};

  /**
   * Fetch available WordPress roles.
   */
  const fetchRoles = useCallback(async () => {
    try {
      const url = buildUrl(
        `${env?.apiBaseUrl || ""}arraysubs/v1/members-access/select/roles`,
      );
      const response = await fetch(url, {
        headers: {
          "X-WP-Nonce": env?.nonce || "",
        },
      });

      if (!response.ok) {
        return;
      }

      const result = await response.json();

      if (result?.success && Array.isArray(result?.data)) {
        // Exclude 'administrator' — admins are always allowed.
        const filtered = result.data.filter(
          (role) => role.value !== "administrator",
        );
        setRoleOptions(filtered);
      }
    } catch {
      // Roles fetch failure is non-critical — the form still works.
    }
  }, [env?.apiBaseUrl, env?.nonce]);

  const loadSettings = useCallback(async () => {
    setLoading(true);
    try {
      const [settings] = await Promise.all([fetchSettings(), fetchRoles()]);
      const flatData = nestedToDot(settings);
      setFormData(flatData);
      form.setFieldsValue(flatData);
    } catch (err) {
      showToast(
        err.message || __("Failed to load settings", "arraysubs"),
        "error",
      );
    } finally {
      setLoading(false);
    }
  }, [form, showToast, fetchRoles]);

  useEffect(() => {
    loadSettings();
  }, [loadSettings]);

  const handleSubmit = async (values) => {
    setSaving(true);
    try {
      const nestedData = dotToNested(values);
      const savedSettings = await saveSettings(nestedData);
      const nextFormData = nestedToDot(savedSettings);
      const previousEnabled = Boolean(
        formData["toolkit.multi_login_prevention"],
      );
      const nextEnabled = Boolean(
        nextFormData["toolkit.multi_login_prevention"],
      );

      window.arraySubs.settings = savedSettings;
      setFormData(nextFormData);
      showToast(__("Settings saved!", "arraysubs"), "success");

      if (previousEnabled !== nextEnabled) {
        window.location.reload();
      }
    } catch (err) {
      showToast(
        err.message || __("Failed to save settings", "arraysubs"),
        "error",
      );
    } finally {
      setSaving(false);
    }
  };

  const handleDiscard = () => {
    form.setFieldsValue(formData);
  };

  if (loading) {
    return (
      <DefaultPageLayout title={__("Toolkit", "arraysubs")}>
        <Skeleton variant="rectangle" width="100%" height={400} />
      </DefaultPageLayout>
    );
  }

  return (
    <DefaultPageLayout
      title={__("Toolkit", "arraysubs")}
      subtitle={__(
        "Control admin bar, dashboard access, login page visibility, and admin tools",
        "arraysubs",
      )}
    >
      <Form form={form} onFinish={handleSubmit} layout="vertical">
        <FormBuilder formItems={getFormStructure(roleOptions)} form={form} />

        <div className="arraysubs-settings-actions arraysubs-bottom-fixed-actions">
          <div>
            <button
              type="submit"
              className="button button-primary"
              disabled={saving}
            >
              {saving
                ? __("Saving...", "arraysubs")
                : __("Save Settings", "arraysubs")}
            </button>
            <button
              type="button"
              className="button"
              onClick={handleDiscard}
              disabled={saving}
            >
              {__("Discard Changes", "arraysubs")}
            </button>
          </div>
        </div>
      </Form>

      <ToastContainer toasts={toasts} removeToast={removeToast} />
    </DefaultPageLayout>
  );
};

export default ToolkitSettings;
