import React, { useState, useEffect, useCallback, useRef } from "react";
import { __, sprintf } from "@wordpress/i18n";
import DefaultPageLayout from "@/components/DefaultPageLayout";
import ProOnlyMessage from "@/components/ProOnlyMessage";
import { getRouteVisiblity } from "@libs/menu-visibility";
import { ToastContainer, useToast } from "@libs/toast";
import Modal from "@libs/modal";
import { buildUrl } from "@/libs/url";
import { formatDateTimeForSite } from "@/libs/dateTime";
import {
  RefreshCw,
  Search,
  Bot,
  ShieldCheck,
  User,
  CreditCard,
  ChevronLeft,
  ChevronRight,
  Lock,
  Eye,
  Info,
  Settings,
} from "lucide-react";

const AUTHOR_ROLES = [
  { value: "", label: __("All Authors", "arraysubs") },
  { value: "system", label: __("System", "arraysubs") },
  { value: "admin", label: __("Admin", "arraysubs") },
  { value: "customer", label: __("Customer", "arraysubs") },
  { value: "gateway", label: __("Gateway", "arraysubs") },
];

const ENTITIES = [
  { value: "", label: __("All Entities", "arraysubs") },
  { value: "subscription", label: __("Subscription", "arraysubs") },
  { value: "member", label: __("Member", "arraysubs") },
  { value: "product", label: __("Product", "arraysubs") },
  { value: "order", label: __("Order", "arraysubs") },
  { value: "coupon", label: __("Coupon", "arraysubs") },
  { value: "email", label: __("Email", "arraysubs") },
  { value: "settings", label: __("Settings", "arraysubs") },
  { value: "other", label: __("Other", "arraysubs") },
];

const AuthorBadge = ({ role, name }) => {
  const icons = {
    system: <Bot size={14} />,
    admin: <ShieldCheck size={14} />,
    customer: <User size={14} />,
    gateway: <CreditCard size={14} />,
  };

  return (
    <span className={`arraysubs-audit-badge arraysubs-audit-badge--${role}`}>
      {icons[role] || <User size={14} />}
      <span>{name}</span>
    </span>
  );
};

const EntityBadge = ({ entity }) => {
  return (
    <span
      className={`arraysubs-audit-entity arraysubs-audit-entity--${entity}`}
    >
      {entity}
    </span>
  );
};

const EntityReferences = ({ references = [] }) => {
  if (!Array.isArray(references) || references.length === 0) {
    return "—";
  }

  return (
    <div className="arraysubs-audit-ref-list">
      {references.map((reference) => {
        const key = `${reference.type}-${reference.id}`;

        if (!reference.href) {
          return (
            <span key={key} className="arraysubs-audit-ref-pill">
              {reference.label}
            </span>
          );
        }

        return (
          <a
            key={key}
            href={reference.href}
            className="arraysubs-audit-ref-pill arraysubs-audit-sub-link"
          >
            {reference.label}
          </a>
        );
      })}
    </div>
  );
};

const VisibilityBadge = ({ noteType }) => {
  if (noteType === "customer") {
    return (
      <span className="arraysubs-audit-visibility arraysubs-audit-visibility--customer">
        <Eye size={13} />
        <span>{__("Customer", "arraysubs")}</span>
      </span>
    );
  }

  return (
    <span className="arraysubs-audit-visibility arraysubs-audit-visibility--private">
      <Lock size={13} />
      <span>{__("Private", "arraysubs")}</span>
    </span>
  );
};

const AuditChangesModal = ({ log, onClose }) => {
  const changes = Array.isArray(log?.audit_changes) ? log.audit_changes : [];
  const entityLabel =
    log?.references?.[0]?.label ||
    log?.entity ||
    __("Audit activity", "arraysubs");

  return (
    <Modal
      isOpen={Boolean(log)}
      onClose={onClose}
      title={sprintf(
        /* translators: %s: entity label. */
        __("Change details — %s", "arraysubs"),
        entityLabel,
      )}
      size="lg"
    >
      <div className="arraysubs-audit-changes-modal">
        <div
          className="arraysubs-audit-changes-modal__summary"
          dangerouslySetInnerHTML={{ __html: log?.content || "" }}
        />

        {changes.length === 0 ? (
          <p className="arraysubs-audit-changes-modal__empty">
            {__(
              "No structured change details are available for this entry.",
              "arraysubs",
            )}
          </p>
        ) : (
          <div className="arraysubs-audit-changes-modal__table-wrap">
            <table className="arraysubs-audit-changes-table">
              <thead>
                <tr>
                  <th>{__("Field", "arraysubs")}</th>
                  <th>{__("Previous Value", "arraysubs")}</th>
                  <th>{__("Changed Value", "arraysubs")}</th>
                </tr>
              </thead>
              <tbody>
                {changes.map((change, index) => (
                  <tr key={`${change.label}-${index}`}>
                    <td>{change.label}</td>
                    <td>{change.previous_value || "—"}</td>
                    <td>{change.changed_value || "—"}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>
    </Modal>
  );
};

const LOGGING_ENTITIES = [
  {
    key: "product",
    label: __("Product", "arraysubs"),
    help: __("Log product-related changes on subscriptions.", "arraysubs"),
  },
  {
    key: "coupon",
    label: __("Coupon", "arraysubs"),
    help: __("Log coupon applications and discount tracking.", "arraysubs"),
  },
  {
    key: "email",
    label: __("Email", "arraysubs"),
    help: __("Log email send events.", "arraysubs"),
  },
  {
    key: "settings",
    label: __("Settings", "arraysubs"),
    help: __("Log plugin settings changes.", "arraysubs"),
  },
];

const LoggingSettingsPopover = ({ showToast }) => {
  const { env } = window.arraySubs;
  const [open, setOpen] = useState(false);
  const [loggingSettings, setLoggingSettings] = useState(null);
  const [saving, setSaving] = useState(false);
  const popoverRef = useRef(null);

  useEffect(() => {
    if (!open) {
      return;
    }
    const url = buildUrl(
      `${env.apiBaseUrl}arraysubs/v1/audits/logging-settings`,
    );
    fetch(url, { headers: { "X-WP-Nonce": env.nonce } })
      .then((res) => {
        if (!res.ok) {
          throw new Error(__("Failed to load logging settings", "arraysubs"));
        }
        return res.json();
      })
      .then((data) => setLoggingSettings(data.content ?? data))
      .catch((err) => showToast(err.message, "error"));
  }, [open]);

  useEffect(() => {
    if (!open) {
      return;
    }
    const handler = (e) => {
      if (popoverRef.current && !popoverRef.current.contains(e.target)) {
        setOpen(false);
      }
    };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, [open]);

  const toggleEntity = async (entity, checked) => {
    const prev = { ...loggingSettings };
    setLoggingSettings((s) => ({ ...s, [entity]: checked }));
    setSaving(true);
    try {
      const url = buildUrl(
        `${env.apiBaseUrl}arraysubs/v1/audits/logging-settings`,
      );
      const res = await fetch(url, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "X-WP-Nonce": env.nonce,
        },
        body: JSON.stringify({ [entity]: checked }),
      });
      if (!res.ok) {
        throw new Error(__("Failed to save setting", "arraysubs"));
      }
      const data = await res.json();
      setLoggingSettings(data.content ?? data);
    } catch (err) {
      setLoggingSettings(prev);
      showToast(err.message, "error");
    } finally {
      setSaving(false);
    }
  };

  return (
    <div className="arraysubs-audit-logging-settings" ref={popoverRef}>
      <button
        type="button"
        className="button button-small"
        onClick={() => setOpen((v) => !v)}
        title={__("Logging Settings", "arraysubs")}
      >
        <Settings size={14} />
      </button>

      {open && (
        <div className="arraysubs-audit-logging-settings__popover">
          <div className="arraysubs-audit-logging-settings__header">
            <strong>{__("Logging Settings", "arraysubs")}</strong>
          </div>

          {!loggingSettings ? (
            <p className="arraysubs-audit-logging-settings__loading">
              {__("Loading...", "arraysubs")}
            </p>
          ) : (
            <>
              <ul className="arraysubs-audit-logging-settings__list">
                {LOGGING_ENTITIES.map((item) => (
                  <li
                    key={item.key}
                    className="arraysubs-audit-logging-settings__item"
                  >
                    <label className="arraysubs-audit-logging-settings__label">
                      <span className="arraysubs-audit-logging-settings__info">
                        <span className="arraysubs-audit-logging-settings__name">
                          {item.label}
                        </span>
                        <span className="arraysubs-audit-logging-settings__help">
                          {item.help}
                        </span>
                      </span>
                      <input
                        type="checkbox"
                        checked={!!loggingSettings[item.key]}
                        onChange={(e) =>
                          toggleEntity(item.key, e.target.checked)
                        }
                        disabled={saving}
                        className="arraysubs-audit-logging-settings__toggle"
                      />
                    </label>
                  </li>
                ))}
              </ul>
              <p className="arraysubs-audit-logging-settings__always-on">
                <Info size={14} aria-hidden="true" />
                <span>
                  {__(
                    "Subscription, Member, Order, and System-level entries are always recorded and cannot be disabled.",
                    "arraysubs",
                  )}
                </span>
              </p>
            </>
          )}
        </div>
      )}
    </div>
  );
};

const AuditContent = () => {
  const { env } = window.arraySubs;
  const { toasts, showToast, removeToast } = useToast();
  const [loading, setLoading] = useState(true);
  const [logs, setLogs] = useState([]);
  const [total, setTotal] = useState(0);
  const [totalPages, setTotalPages] = useState(0);
  const [page, setPage] = useState(1);
  const perPage = 30;

  const [filters, setFilters] = useState({
    author_role: "",
    entity: "",
    date_from: "",
    date_to: "",
    search: "",
  });
  const [selectedLog, setSelectedLog] = useState(null);

  const fetchLogs = useCallback(
    async (currentPage = 1, currentFilters = filters) => {
      setLoading(true);
      try {
        const params = {
          page: currentPage,
          per_page: perPage,
        };

        if (currentFilters.author_role) {
          params.author_role = currentFilters.author_role;
        }
        if (currentFilters.entity) {
          params.entity = currentFilters.entity;
        }
        if (currentFilters.date_from) {
          params.date_from = currentFilters.date_from;
        }
        if (currentFilters.date_to) {
          params.date_to = currentFilters.date_to;
        }
        if (currentFilters.search) {
          params.search = currentFilters.search;
        }

        const url = buildUrl(
          `${env.apiBaseUrl}arraysubs/v1/audits/activity-logs`,
          params,
        );
        const response = await fetch(url, {
          headers: { "X-WP-Nonce": env.nonce },
        });

        if (!response.ok) {
          throw new Error(__("Failed to fetch audit logs", "arraysubs"));
        }

        const result = await response.json();
        setLogs(result.content?.logs || []);
        setTotal(result.content?.total || 0);
        setTotalPages(result.content?.total_pages || 0);
        setPage(result.content?.page || 1);
      } catch (error) {
        showToast(error.message, "error");
      } finally {
        setLoading(false);
      }
    },
    [env, filters],
  );

  useEffect(() => {
    fetchLogs(1, filters);
  }, []);

  const handleFilterChange = (key, value) => {
    const updated = { ...filters, [key]: value };
    setFilters(updated);
    if (key !== "search") {
      fetchLogs(1, updated);
    }
  };

  const handleSearchKeyDown = (e) => {
    if (e.key === "Enter") {
      fetchLogs(1, filters);
    }
  };

  const handlePageChange = (newPage) => {
    if (newPage < 1 || newPage > totalPages) {
      return;
    }
    fetchLogs(newPage, filters);
  };

  const handleReset = () => {
    const reset = {
      author_role: "",
      entity: "",
      date_from: "",
      date_to: "",
      search: "",
    };
    setFilters(reset);
    fetchLogs(1, reset);
  };

  const formatTimestamp = (ts) => {
    if (!ts) {
      return "—";
    }
    return formatDateTimeForSite(ts, "—");
  };

  return (
    <>
      {/* Filter Bar */}
      <div className="arraysubs-audit-filters">
        <div className="arraysubs-audit-filters__row">
          <select
            value={filters.author_role}
            onChange={(e) => handleFilterChange("author_role", e.target.value)}
            className="arraysubs-audit-filters__select"
          >
            {AUTHOR_ROLES.map((r) => (
              <option key={r.value} value={r.value}>
                {r.label}
              </option>
            ))}
          </select>

          <select
            value={filters.entity}
            onChange={(e) => handleFilterChange("entity", e.target.value)}
            className="arraysubs-audit-filters__select"
          >
            {ENTITIES.map((e) => (
              <option key={e.value} value={e.value}>
                {e.label}
              </option>
            ))}
          </select>

          <input
            type="date"
            value={filters.date_from}
            onChange={(e) => handleFilterChange("date_from", e.target.value)}
            className="arraysubs-audit-filters__date"
            placeholder={__("From", "arraysubs")}
          />

          <input
            type="date"
            value={filters.date_to}
            onChange={(e) => handleFilterChange("date_to", e.target.value)}
            className="arraysubs-audit-filters__date"
            placeholder={__("To", "arraysubs")}
          />

          <div className="arraysubs-audit-filters__search">
            <Search size={16} />
            <input
              type="text"
              value={filters.search}
              onChange={(e) => handleFilterChange("search", e.target.value)}
              onKeyDown={handleSearchKeyDown}
              placeholder={__("Search logs... (Enter)", "arraysubs")}
            />
          </div>

          <button
            type="button"
            className="button button-small"
            onClick={handleReset}
          >
            {__("Reset", "arraysubs")}
          </button>

          <button
            type="button"
            className="button button-small"
            onClick={() => fetchLogs(page, filters)}
            disabled={loading}
          >
            <RefreshCw size={14} className={loading ? "arraysubs-spin" : ""} />
          </button>

          <LoggingSettingsPopover showToast={showToast} />
        </div>
      </div>

      {/* Log Table */}
      <div className="arraysubs-audit-table-wrap">
        {loading && logs.length === 0 ? (
          <p className="arraysubs-loading">
            {__("Loading audit logs...", "arraysubs")}
          </p>
        ) : logs.length === 0 ? (
          <p className="arraysubs-audit-empty">
            {__("No audit logs found for the selected filters.", "arraysubs")}
          </p>
        ) : (
          <table className="wp-list-table widefat fixed striped arraysubs-audit-table">
            <thead>
              <tr>
                <th className="arraysubs-audit-table__col--date">
                  {__("Date", "arraysubs")}
                </th>
                <th className="arraysubs-audit-table__col--meta">
                  {__("Meta", "arraysubs")}
                </th>
                <th className="arraysubs-audit-table__col--sub">
                  {__("Entity", "arraysubs")}
                </th>
                <th className="arraysubs-audit-table__col--desc">
                  {__("Activity", "arraysubs")}
                </th>
              </tr>
            </thead>
            <tbody>
              {logs.map((log) => (
                <tr key={log.id}>
                  <td className="arraysubs-audit-table__col--date">
                    {formatTimestamp(log.date_timestamp)}
                  </td>
                  <td className="arraysubs-audit-table__col--meta">
                    <div className="arraysubs-audit-meta">
                      <AuthorBadge
                        role={log.author_role}
                        name={log.author_name}
                      />
                      <EntityBadge entity={log.entity} />
                      <VisibilityBadge noteType={log.note_type} />
                    </div>
                  </td>
                  <td className="arraysubs-audit-table__col--sub">
                    <EntityReferences references={log.references} />
                  </td>
                  <td className="arraysubs-audit-table__col--desc">
                    <div className="arraysubs-audit-activity">
                      <div
                        className="arraysubs-audit-activity__content"
                        dangerouslySetInnerHTML={{ __html: log.content }}
                      />
                      {log.has_audit_changes ? (
                        <a
                          href="#"
                          className="arraysubs-audit-activity__changes-link"
                          onClick={(event) => {
                            event.preventDefault();
                            setSelectedLog(log);
                          }}
                        >
                          {__("changes ->", "arraysubs")}
                        </a>
                      ) : null}
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>

      {/* Pagination */}
      {totalPages > 1 && (
        <div className="arraysubs-audit-pagination">
          <button
            type="button"
            className="button button-small"
            disabled={page <= 1}
            onClick={() => handlePageChange(page - 1)}
          >
            <ChevronLeft size={16} />
            {__("Previous", "arraysubs")}
          </button>
          <span className="arraysubs-audit-pagination__info">
            {__("Page", "arraysubs")} {page} {__("of", "arraysubs")}{" "}
            {totalPages}
            <span className="arraysubs-audit-pagination__total">
              ({total} {__("total", "arraysubs")})
            </span>
          </span>
          <button
            type="button"
            className="button button-small"
            disabled={page >= totalPages}
            onClick={() => handlePageChange(page + 1)}
          >
            {__("Next", "arraysubs")}
            <ChevronRight size={16} />
          </button>
        </div>
      )}

      <ToastContainer toasts={toasts} removeToast={removeToast} />
      <AuditChangesModal
        log={selectedLog}
        onClose={() => setSelectedLog(null)}
      />
    </>
  );
};

const ActivityAudits = () => {
  const menuItems = window.arraySubs?.menu?.items || [];
  const visibility = getRouteVisiblity("/audits/activity-audits", menuItems);
  const isProActive = visibility === 1;

  return (
    <DefaultPageLayout
      title={__("Activity Audits", "arraysubs")}
      subtitle={
        isProActive
          ? __(
              "View all subscription activity logs, system actions, and user events.",
              "arraysubs",
            )
          : ""
      }
    >
      {isProActive ? <AuditContent /> : <ProOnlyMessage />}
    </DefaultPageLayout>
  );
};

export default ActivityAudits;
