// Rules management view — visual, non-technical rule builder for alerts.

const { useState: useRuleState, useMemo: useRuleMemo, useEffect: useRuleEffect } = React;

const RULE_TEMPLATES = {
  threshold: {
    name: "",
    description: "",
    rule_type: "threshold",
    severity: "medium",
    priority: 5,
    condition: { operator: "gt", field: "amount", value: 10000 },
    actions: [{ action: "create_alert", params: {} }],
    lookback_seconds: 86400,
    aggregation_key: null,
    tags: [],
  },
  list_match: {
    name: "",
    description: "",
    rule_type: "list_match",
    severity: "high",
    priority: 4,
    condition: { operator: "in", field: "originator_country", value: ["XX", "YY"] },
    actions: [{ action: "create_alert", params: {} }],
    lookback_seconds: 86400,
    aggregation_key: null,
    tags: [],
  },
  velocity: {
    name: "",
    description: "",
    rule_type: "velocity",
    severity: "high",
    priority: 3,
    condition: { operator: "gt", field: "amount", value: 50000 },
    actions: [{ action: "create_alert", params: {} }],
    lookback_seconds: 86400,
    aggregation_key: "originator_id",
    tags: [],
  },
  anomaly: {
    name: "",
    description: "",
    rule_type: "anomaly",
    severity: "high",
    priority: 3,
    condition: { operator: "gt", field: "risk_score", value: 75 },
    actions: [{ action: "create_alert", params: {} }],
    lookback_seconds: 86400,
    aggregation_key: null,
    tags: [],
  },
  composite: {
    name: "",
    description: "",
    rule_type: "composite",
    severity: "critical",
    priority: 1,
    condition: {
      operator: "and",
      conditions: [
        { operator: "gt", field: "amount", value: 50000 },
        { operator: "in", field: "originator_country", value: ["XX", "YY"] },
      ],
    },
    actions: [{ action: "create_alert", params: {} }],
    lookback_seconds: 86400,
    aggregation_key: null,
    tags: [],
  },
};

const TRANSACTION_TYPES = ["wire", "ach", "card", "atm", "crypto", "cash"];

const FIELD_OPTIONS = [
  { value: "amount", label: "Amount", type: "number", placeholder: "e.g. 10000" },
  { value: "risk_score", label: "Risk score", type: "number", placeholder: "0-100" },
  { value: "transaction_type", label: "Transaction type", type: "txn_type", placeholder: "e.g. card" },
  { value: "originator_country", label: "Originator country", type: "country", placeholder: "e.g. US" },
  { value: "beneficiary_country", label: "Beneficiary country", type: "country", placeholder: "e.g. US" },
  { value: "originator_id", label: "Originator ID", type: "text", placeholder: "e.g. C123456" },
  { value: "beneficiary_id", label: "Beneficiary ID", type: "text", placeholder: "e.g. M123456" },
];

const OPERATORS_BY_TYPE = {
  number: [
    { value: "gt", label: "is greater than" },
    { value: "gte", label: "is greater than or equal to" },
    { value: "lt", label: "is less than" },
    { value: "lte", label: "is less than or equal to" },
    { value: "eq", label: "equals" },
    { value: "ne", label: "does not equal" },
    { value: "between", label: "is between" },
  ],
  text: [
    { value: "eq", label: "equals" },
    { value: "ne", label: "does not equal" },
    { value: "in", label: "is one of" },
    { value: "not_in", label: "is not one of" },
    { value: "contains", label: "contains" },
    { value: "regex", label: "matches pattern" },
  ],
  country: [
    { value: "eq", label: "equals" },
    { value: "ne", label: "does not equal" },
    { value: "in", label: "is one of" },
    { value: "not_in", label: "is not one of" },
  ],
  txn_type: [
    { value: "in", label: "is one of" },
    { value: "not_in", label: "is not one of" },
  ],
};

const ACTION_OPTIONS = [
  { value: "create_alert", label: "Create alert", needsParam: false },
  { value: "add_score", label: "Add risk score", needsParam: true, paramName: "score", paramLabel: "Score to add", paramType: "number" },
  { value: "tag", label: "Tag transaction", needsParam: true, paramName: "tag", paramLabel: "Tag", paramType: "text" },
  { value: "escalate", label: "Escalate", needsParam: false },
  { value: "block", label: "Block", needsParam: false },
];

const STATUS_PILL = {
  active: "ok",
  draft: "med",
  paused: "warn",
  archived: "low",
};

function getFieldType(field) {
  return FIELD_OPTIONS.find(f => f.value === field)?.type || "text";
}

function getFieldLabel(field) {
  return FIELD_OPTIONS.find(f => f.value === field)?.label || field;
}

function getOperatorLabel(op) {
  for (const type of Object.values(OPERATORS_BY_TYPE)) {
    const found = type.find(o => o.value === op);
    if (found) return found.label;
  }
  return op;
}

function formatValue(value, operator) {
  if (value == null) return "—";
  if (Array.isArray(value)) return value.join(", ");
  if (typeof value === "object") return JSON.stringify(value);
  return String(value);
}

function conditionToSentence(condition) {
  if (!condition) return "No condition";
  if (condition.operator === "and" || condition.operator === "or") {
    const parts = (condition.conditions || []).map(conditionToSentence).filter(Boolean);
    if (parts.length === 0) return "No condition";
    if (parts.length === 1) return parts[0];
    return parts.join(` ${condition.operator.toUpperCase()} `);
  }
  if (condition.operator === "not") {
    const sub = condition.conditions?.[0];
    return sub ? `NOT (${conditionToSentence(sub)})` : "NOT (empty)";
  }
  return `${getFieldLabel(condition.field)} ${getOperatorLabel(condition.operator)} ${formatValue(condition.value, condition.operator)}`;
}

function isListOperator(op) {
  return op === "in" || op === "not_in";
}

function isBetweenOperator(op) {
  return op === "between";
}

function parseListValue(raw) {
  return String(raw || "").split(",").map(s => s.trim()).filter(Boolean);
}

function serializeListValue(value) {
  return Array.isArray(value) ? value.join(", ") : String(value || "");
}

function ensureNumberArray(value) {
  if (Array.isArray(value) && value.length === 2) return [Number(value[0]) || 0, Number(value[1]) || 0];
  return [0, 0];
}

function ConditionRow({ condition, onChange, onRemove, showRemove }) {
  const fieldType = getFieldType(condition.field);
  const operators = OPERATORS_BY_TYPE[fieldType] || OPERATORS_BY_TYPE.text;

  const updateField = (field) => {
    const newType = getFieldType(field);
    const newOperators = OPERATORS_BY_TYPE[newType] || OPERATORS_BY_TYPE.text;
    const newOp = newOperators.find(o => o.value === condition.operator)?.value
      ? condition.operator
      : newOperators[0].value;
    onChange({ ...condition, field, operator: newOp, value: isListOperator(newOp) ? [] : (isBetweenOperator(newOp) ? [0, 0] : "") });
  };

  const updateOperator = (operator) => {
    let value = condition.value;
    if (isListOperator(operator) && !Array.isArray(value)) value = [];
    if (isBetweenOperator(operator) && !Array.isArray(value)) value = [0, 0];
    if (!isListOperator(operator) && !isBetweenOperator(operator) && Array.isArray(value)) value = "";
    onChange({ ...condition, operator, value });
  };

  const renderValueInput = () => {
    if (fieldType === "txn_type") {
      const selected = Array.isArray(condition.value) ? condition.value : (condition.value ? [condition.value] : []);
      return (
        <div style={{ display: "flex", flexWrap: "wrap", gap: "6px 12px", padding: "6px 8px", background: "var(--bg)", border: "1px solid var(--border)", borderRadius: 6 }}>
          {TRANSACTION_TYPES.map(t => {
            const checked = selected.includes(t);
            return (
              <label key={t} style={{ display: "inline-flex", alignItems: "center", gap: 5, fontSize: 12, cursor: "pointer", userSelect: "none" }}>
                <input
                  type="checkbox"
                  checked={checked}
                  onChange={() => {
                    const next = checked ? selected.filter(x => x !== t) : [...selected, t];
                    onChange({ ...condition, value: next });
                  }}
                />
                <span style={{ textTransform: "capitalize" }}>{t}</span>
              </label>
            );
          })}
        </div>
      );
    }
    if (isListOperator(condition.operator)) {
      return (
        <input
          className="field"
          value={serializeListValue(condition.value)}
          onChange={e => onChange({ ...condition, value: parseListValue(e.target.value) })}
          placeholder="comma-separated values"
        />
      );
    }
    if (isBetweenOperator(condition.operator)) {
      const [min, max] = ensureNumberArray(condition.value);
      return (
        <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
          <input className="field" type="number" value={min} onChange={e => onChange({ ...condition, value: [Number(e.target.value), max] })} placeholder="min" />
          <span style={{ color: "var(--fg-3)" }}>and</span>
          <input className="field" type="number" value={max} onChange={e => onChange({ ...condition, value: [min, Number(e.target.value)] })} placeholder="max" />
        </div>
      );
    }
    if (fieldType === "number") {
      return (
        <input
          className="field"
          type="number"
          value={condition.value ?? ""}
          onChange={e => onChange({ ...condition, value: Number(e.target.value) })}
          placeholder={FIELD_OPTIONS.find(f => f.value === condition.field)?.placeholder || ""}
        />
      );
    }
    return (
      <input
        className="field"
        value={condition.value ?? ""}
        onChange={e => onChange({ ...condition, value: e.target.value })}
        placeholder={FIELD_OPTIONS.find(f => f.value === condition.field)?.placeholder || ""}
      />
    );
  };

  return (
    <div style={{ display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap", padding: 10, background: "var(--bg-2)", borderRadius: 6, border: "1px solid var(--border)" }}>
      <select className="field" value={condition.field} onChange={e => updateField(e.target.value)} style={{ minWidth: 160 }}>
        {FIELD_OPTIONS.map(f => <option key={f.value} value={f.value}>{f.label}</option>)}
      </select>
      <select className="field" value={condition.operator} onChange={e => updateOperator(e.target.value)} style={{ minWidth: 170 }}>
        {operators.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
      </select>
      <div style={{ minWidth: 180, flex: 1 }}>{renderValueInput()}</div>
      {showRemove && (
        <button type="button" className="btn ghost icon sm" onClick={onRemove} title="Remove condition">
          <Icon.X size={12} />
        </button>
      )}
    </div>
  );
}

function ConditionBuilder({ ruleType, condition, onChange }) {
  const isComposite = ruleType === "composite";

  if (!isComposite) {
    return (
      <ConditionRow
        condition={condition || { operator: "gt", field: "amount", value: "" }}
        onChange={onChange}
        showRemove={false}
      />
    );
  }

  const composite = condition?.operator === "and" || condition?.operator === "or"
    ? condition
    : { operator: "and", conditions: [condition || { operator: "gt", field: "amount", value: "" }] };

  const updateLogic = (operator) => onChange({ ...composite, operator });

  const updateCondition = (idx, newCond) => {
    const conditions = [...composite.conditions];
    conditions[idx] = newCond;
    onChange({ ...composite, conditions });
  };

  const addCondition = () => {
    onChange({ ...composite, conditions: [...composite.conditions, { operator: "gt", field: "amount", value: "" }] });
  };

  const removeCondition = (idx) => {
    const conditions = composite.conditions.filter((_, i) => i !== idx);
    onChange({ ...composite, conditions });
  };

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
      <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
        <span style={{ fontSize: 12, color: "var(--fg-3)" }}>Match</span>
        <select className="field" value={composite.operator} onChange={e => updateLogic(e.target.value)} style={{ width: 80 }}>
          <option value="and">ALL</option>
          <option value="or">ANY</option>
        </select>
        <span style={{ fontSize: 12, color: "var(--fg-3)" }}>of the following conditions</span>
      </div>
      {composite.conditions.map((c, i) => (
        <ConditionRow
          key={i}
          condition={c}
          onChange={(newC) => updateCondition(i, newC)}
          onRemove={() => removeCondition(i)}
          showRemove={composite.conditions.length > 1}
        />
      ))}
      <div>
        <button type="button" className="btn sm" onClick={addCondition}>
          <Icon.Plus size={11} /> Add condition
        </button>
      </div>
    </div>
  );
}

function ActionBuilder({ actions, onChange }) {
  const updateAction = (idx, updates) => {
    const next = actions.map((a, i) => i === idx ? { ...a, ...updates } : a);
    onChange(next);
  };

  const addAction = () => onChange([...actions, { action: "create_alert", params: {} }]);
  const removeAction = (idx) => onChange(actions.filter((_, i) => i !== idx));

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
      {actions.map((action, i) => {
        const meta = ACTION_OPTIONS.find(a => a.value === action.action) || ACTION_OPTIONS[0];
        return (
          <div key={i} style={{ display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }}>
            <select
              className="field"
              value={action.action}
              onChange={e => {
                const newMeta = ACTION_OPTIONS.find(a => a.value === e.target.value);
                updateAction(i, { action: e.target.value, params: newMeta.needsParam ? { [newMeta.paramName]: newMeta.paramType === "number" ? 0 : "" } : {} });
              }}
              style={{ minWidth: 180 }}
            >
              {ACTION_OPTIONS.map(a => <option key={a.value} value={a.value}>{a.label}</option>)}
            </select>
            {meta.needsParam && (
              <input
                className="field"
                type={meta.paramType}
                value={action.params[meta.paramName] ?? ""}
                onChange={e => updateAction(i, { params: { [meta.paramName]: meta.paramType === "number" ? Number(e.target.value) : e.target.value } })}
                placeholder={meta.paramLabel}
                style={{ minWidth: 120 }}
              />
            )}
            {actions.length > 1 && (
              <button type="button" className="btn ghost icon sm" onClick={() => removeAction(i)}>
                <Icon.X size={12} />
              </button>
            )}
          </div>
        );
      })}
      <div>
        <button type="button" className="btn sm" onClick={addAction}>
          <Icon.Plus size={11} /> Add action
        </button>
      </div>
    </div>
  );
}

function RuleEditor({ rule, onSave, onCancel }) {
  const isNew = !rule;
  const [form, setForm] = useRuleState(() => {
    const base = rule ? { ...rule } : RULE_TEMPLATES.threshold;
    return {
      ...base,
      tags: Array.isArray(base.tags) ? base.tags.join(", ") : "",
    };
  });
  const [error, setError] = useRuleState(null);
  const [saving, setSaving] = useRuleState(false);

  const update = (key, value) => setForm(f => ({ ...f, [key]: value }));

  const applyTemplate = (type) => {
    const tpl = RULE_TEMPLATES[type];
    setForm(f => ({
      ...f,
      ...tpl,
      name: f.name || tpl.name,
      description: f.description || tpl.description,
      tags: f.tags || "",
    }));
  };

  const validate = () => {
    if (!form.name.trim()) return "Rule name is required";
    if (form.rule_type === "composite") {
      if (!form.condition || !Array.isArray(form.condition.conditions) || form.condition.conditions.length === 0) {
        return "Composite rules need at least one condition";
      }
    } else {
      if (!form.condition || !form.condition.field || !form.condition.operator) {
        return "Condition is incomplete";
      }
    }
    if (!Array.isArray(form.actions) || form.actions.length === 0) return "At least one action is required";
    return null;
  };

  const submit = async (e) => {
    e.preventDefault();
    setError(null);
    const validationError = validate();
    if (validationError) {
      setError(validationError);
      return;
    }
    const payload = {
      name: form.name,
      description: form.description || null,
      rule_type: form.rule_type,
      severity: form.severity,
      priority: Number(form.priority),
      condition: form.condition,
      actions: form.actions,
      lookback_seconds: Number(form.lookback_seconds),
      aggregation_key: form.aggregation_key || null,
      effective_from: form.effective_from || null,
      tags: form.tags.split(",").map(t => t.trim()).filter(Boolean),
    };
    setSaving(true);
    try {
      await onSave(payload);
    } catch (err) {
      setError(err.message);
    } finally {
      setSaving(false);
    }
  };

  return (
    <div className="card" style={{ margin: "18px auto", maxWidth: 800, maxHeight: "calc(100vh - 120px)", overflow: "auto", display: "flex", flexDirection: "column" }}>
      <div className="card-hd" style={{ flexShrink: 0 }}>
        <h3>{isNew ? "New detection rule" : "Edit rule"}</h3>
        <span className="spacer" />
        <button className="btn ghost sm" onClick={onCancel}>Cancel</button>
      </div>
      <form onSubmit={submit} className="card-body" style={{ display: "flex", flexDirection: "column", gap: 18, overflow: "auto", paddingBottom: 24 }}>
        {error && <div style={{ color: "var(--risk-high)", fontSize: 12.5 }}>{error}</div>}

        {isNew && (
          <div>
            <label style={{ display: "block", fontSize: 11.5, color: "var(--fg-3)", marginBottom: 6 }}>Start from template</label>
            <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
              {Object.keys(RULE_TEMPLATES).map(t => (
                <button key={t} type="button" className="btn sm" onClick={() => applyTemplate(t)}>
                  {t.replace("_", " ")}
                </button>
              ))}
            </div>
          </div>
        )}

        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          <div>
            <label style={{ display: "block", fontSize: 11.5, color: "var(--fg-3)", marginBottom: 4 }}>Rule name</label>
            <input className="field" value={form.name} onChange={e => update("name", e.target.value)} required placeholder="e.g. Large wire transfer" />
          </div>
          <div>
            <label style={{ display: "block", fontSize: 11.5, color: "var(--fg-3)", marginBottom: 4 }}>Rule type</label>
            <select className="field" value={form.rule_type} onChange={e => applyTemplate(e.target.value)}>
              <option value="threshold">Threshold</option>
              <option value="velocity">Velocity</option>
              <option value="list_match">List match</option>
              <option value="anomaly">Anomaly</option>
              <option value="composite">Composite</option>
            </select>
          </div>
        </div>

        <div>
          <label style={{ display: "block", fontSize: 11.5, color: "var(--fg-3)", marginBottom: 4 }}>Description</label>
          <input className="field" value={form.description || ""} onChange={e => update("description", e.target.value)} placeholder="What does this rule detect?" />
        </div>

        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 12 }}>
          <div>
            <label style={{ display: "block", fontSize: 11.5, color: "var(--fg-3)", marginBottom: 4 }}>Severity</label>
            <select className="field" value={form.severity} onChange={e => update("severity", e.target.value)}>
              <option value="low">Low</option>
              <option value="medium">Medium</option>
              <option value="high">High</option>
              <option value="critical">Critical</option>
            </select>
          </div>
          <div>
            <label style={{ display: "block", fontSize: 11.5, color: "var(--fg-3)", marginBottom: 4 }}>Priority (1-10)</label>
            <input className="field" type="number" min="1" max="10" value={form.priority} onChange={e => update("priority", e.target.value)} required />
          </div>
          <div>
            <label style={{ display: "block", fontSize: 11.5, color: "var(--fg-3)", marginBottom: 4 }}>Lookback (days)</label>
            <input className="field" type="number" step="0.1" min="0"
                   value={form.lookback_seconds === "" ? "" : form.lookback_seconds / 86400}
                   onChange={e => update("lookback_seconds", e.target.value === "" ? "" : Number(e.target.value) * 86400)} />
          </div>
        </div>

        <div style={{ maxWidth: 360 }}>
          <label style={{ display: "block", fontSize: 11.5, color: "var(--fg-3)", marginBottom: 4 }}>Effective from</label>
          <input
            className="field"
            type="datetime-local"
            value={form.effective_from ? new Date(form.effective_from).toISOString().slice(0, 16) : ""}
            onChange={e => update("effective_from", e.target.value ? new Date(e.target.value).toISOString() : null)}
          />
          <span style={{ fontSize: 10.5, color: "var(--fg-3)" }}>Leave blank to activate immediately</span>
        </div>

        {form.rule_type === "velocity" && (
          <div>
            <label style={{ display: "block", fontSize: 11.5, color: "var(--fg-3)", marginBottom: 4 }}>Aggregate by</label>
            <select className="field" value={form.aggregation_key || ""} onChange={e => update("aggregation_key", e.target.value)}>
              <option value="">—</option>
              <option value="originator_id">Originator ID</option>
              <option value="beneficiary_id">Beneficiary ID</option>
            </select>
          </div>
        )}

        <div>
          <label style={{ display: "block", fontSize: 11.5, color: "var(--fg-3)", marginBottom: 8 }}>When should this rule trigger?</label>
          <ConditionBuilder
            ruleType={form.rule_type}
            condition={form.condition}
            onChange={(c) => update("condition", c)}
          />
          <div style={{ marginTop: 10, padding: 12, background: "var(--accent-tint)", borderRadius: 6, fontSize: 12.5, color: "var(--fg-2)", lineHeight: 1.5 }}>
            <b>Preview:</b> Alert when {conditionToSentence(form.condition)}
          </div>
        </div>

        <div>
          <label style={{ display: "block", fontSize: 11.5, color: "var(--fg-3)", marginBottom: 8 }}>Actions</label>
          <ActionBuilder actions={form.actions} onChange={(a) => update("actions", a)} />
        </div>

        <div>
          <label style={{ display: "block", fontSize: 11.5, color: "var(--fg-3)", marginBottom: 4 }}>Tags (comma-separated)</label>
          <input className="field" value={form.tags} onChange={e => update("tags", e.target.value)} placeholder="aml, structuring, high-risk" />
        </div>

        <div style={{ display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 8 }}>
          <button className="btn" type="button" onClick={onCancel}>Cancel</button>
          <button className="btn primary" type="submit" disabled={saving}>{saving ? "Saving…" : "Save rule"}</button>
        </div>
      </form>
    </div>
  );
}

function SimulationPanel({ rules }) {
  const [selectedRuleId, setSelectedRuleId] = useRuleState("");
  const [amountThreshold, setAmountThreshold] = useRuleState("");
  const [countThreshold, setCountThreshold] = useRuleState("");
  const [startDate, setStartDate] = useRuleState("");
  const [endDate, setEndDate] = useRuleState("");
  const [entityId, setEntityId] = useRuleState("");
  const [loading, setLoading] = useRuleState(false);
  const [result, setResult] = useRuleState(null);
  const [error, setError] = useRuleState(null);

  useRuleEffect(() => {
    const end = new Date();
    const start = new Date();
    start.setDate(start.getDate() - 90);
    setEndDate(end.toISOString().slice(0, 10));
    setStartDate(start.toISOString().slice(0, 10));
  }, []);

  useRuleEffect(() => {
    if (rules && rules.length && !selectedRuleId) {
      const first = rules[0];
      setSelectedRuleId(first.id);
      setAmountThreshold(String(first.condition?.value || ""));
    }
  }, [rules]);

  const run = async () => {
    if (!selectedRuleId || !startDate || !endDate) return;
    setLoading(true);
    setError(null);
    setResult(null);
    try {
      const overrides = {};
      const overrideCondition = {};
      if (amountThreshold !== "") overrideCondition.value = Number(amountThreshold);
      if (countThreshold !== "") overrideCondition.count = Number(countThreshold);
      if (Object.keys(overrideCondition).length) {
        overrides[selectedRuleId] = overrideCondition;
      }
      const body = {
        rule_ids: [selectedRuleId],
        condition_overrides: overrides,
        start_date: new Date(startDate).toISOString(),
        end_date: new Date(endDate + "T23:59:59Z").toISOString(),
        entity_scope: entityId.trim() ? "specific_entity" : "all",
        entity_id: entityId.trim() || null,
      };
      const res = await window.mossadApi.simulateRules(body);
      setResult(res);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  const selectedRule = rules.find(r => r.id === selectedRuleId);

  return (
    <div className="card">
      <div className="card-hd">
        <h3>Rule backtesting</h3>
        <span className="spacer" />
        <span className="mono muted" style={{ fontSize: 11 }}>Simulate thresholds without changing production rules</span>
      </div>
      <div className="card-body">
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))", gap: 12, marginBottom: 16 }}>
          <div>
            <div className="kpi-label">Rule</div>
            <select
              value={selectedRuleId}
              onChange={e => {
                setSelectedRuleId(e.target.value);
                const r = rules.find(x => x.id === e.target.value);
                if (r) setAmountThreshold(String(r.condition?.value || ""));
              }}
              style={{ width: "100%", padding: 8, borderRadius: 6, border: "1px solid var(--border)", background: "var(--bg-2)", color: "var(--fg)" }}
            >
              {rules.map(r => <option key={r.id} value={r.id}>{r.name}</option>)}
            </select>
          </div>
          <div>
            <div className="kpi-label">Amount threshold</div>
            <input
              type="number"
              value={amountThreshold}
              onChange={e => setAmountThreshold(e.target.value)}
              placeholder={selectedRule?.condition?.value ?? "e.g. 10000"}
              style={{ width: "100%", padding: 8, borderRadius: 6, border: "1px solid var(--border)", background: "var(--bg-2)", color: "var(--fg)" }}
            />
          </div>
          <div>
            <div className="kpi-label">Count threshold</div>
            <input
              type="number"
              value={countThreshold}
              onChange={e => setCountThreshold(e.target.value)}
              placeholder="velocity only"
              style={{ width: "100%", padding: 8, borderRadius: 6, border: "1px solid var(--border)", background: "var(--bg-2)", color: "var(--fg)" }}
            />
          </div>
          <div>
            <div className="kpi-label">Specific entity ID (optional)</div>
            <input
              type="text"
              value={entityId}
              onChange={e => setEntityId(e.target.value)}
              placeholder="e.g. C123456 or customer hash"
              style={{ width: "100%", padding: 8, borderRadius: 6, border: "1px solid var(--border)", background: "var(--bg-2)", color: "var(--fg)" }}
            />
          </div>
          <div>
            <div className="kpi-label">Start date</div>
            <input
              type="date"
              value={startDate}
              onChange={e => setStartDate(e.target.value)}
              style={{ width: "100%", padding: 8, borderRadius: 6, border: "1px solid var(--border)", background: "var(--bg-2)", color: "var(--fg)" }}
            />
          </div>
          <div>
            <div className="kpi-label">End date</div>
            <input
              type="date"
              value={endDate}
              onChange={e => setEndDate(e.target.value)}
              style={{ width: "100%", padding: 8, borderRadius: 6, border: "1px solid var(--border)", background: "var(--bg-2)", color: "var(--fg)" }}
            />
          </div>
        </div>
        <div style={{ display: "flex", gap: 8, marginBottom: 16 }}>
          <button className="btn primary" onClick={run} disabled={loading || !selectedRuleId}>
            {loading ? "Running…" : <><Icon.Bolt size={12} /> Run simulation</>}
          </button>
        </div>
        {error && (
          <div style={{ padding: 10, background: "var(--risk-high-bg)", color: "var(--risk-high)", borderRadius: 6, fontSize: 12, marginBottom: 12 }}>
            {error}
          </div>
        )}
        {result && (
          <div>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 12, marginBottom: 16 }}>
              <div className="kpi-card">
                <div className="kpi-value">{result.total_alerts_generated.toLocaleString()}</div>
                <div className="kpi-label">Alerts generated</div>
              </div>
              <div className="kpi-card">
                <div className="kpi-value">{result.unique_entities_flagged.toLocaleString()}</div>
                <div className="kpi-label">Entities flagged</div>
              </div>
              <div className="kpi-card">
                <div className="kpi-value">{result.existing_cases_covered.toLocaleString()}</div>
                <div className="kpi-label">Existing cases covered</div>
              </div>
              <div className="kpi-card">
                <div className="kpi-value">{result.existing_sars_covered.toLocaleString()}</div>
                <div className="kpi-label">Existing SARs covered</div>
              </div>
            </div>
            <h4 style={{ fontSize: 13, marginBottom: 8 }}>Rule breakdown</h4>
            <table className="tbl" style={{ marginBottom: 16 }}>
              <thead>
                <tr>
                  <th>Rule</th>
                  <th>Type</th>
                  <th className="right">Evaluated</th>
                  <th className="right">Alerts</th>
                  <th className="right">Entities</th>
                </tr>
              </thead>
              <tbody>
                {result.rule_breakdown.map(rb => (
                  <tr key={rb.rule_id}>
                    <td>{rb.rule_name}</td>
                    <td><span className="pill outline">{rb.rule_type}</span></td>
                    <td className="right mono">{rb.transactions_evaluated.toLocaleString()}</td>
                    <td className="right mono">{rb.alerts_generated.toLocaleString()}</td>
                    <td className="right mono">{rb.unique_entities.toLocaleString()}</td>
                  </tr>
                ))}
              </tbody>
            </table>
            {result.sample_alerts.length > 0 && (
              <>
                <h4 style={{ fontSize: 13, marginBottom: 8 }}>Sample alerts</h4>
                <table className="tbl">
                  <thead>
                    <tr>
                      <th>Entity</th>
                      <th>Rule</th>
                      <th>Txn ID</th>
                      <th className="right">Amount</th>
                      <th>Severity</th>
                    </tr>
                  </thead>
                  <tbody>
                    {result.sample_alerts.slice(0, 10).map((sa, i) => (
                      <tr key={i}>
                        <td className="mono">{sa.primary_entity_id}</td>
                        <td>{sa.rule_name}</td>
                        <td className="mono">{sa.external_id || sa.transaction_id.slice(0, 8)}</td>
                        <td className="right mono">${Number(sa.amount).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} {sa.currency}</td>
                        <td><span className={`pill ${sa.severity === "medium" ? "med" : sa.severity || "low"}`}>{sa.severity}</span></td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

function RulesView({ data }) {
  const rules = data?.rules || window.RULES_API || [];
  const [editing, setEditing] = useRuleState(null);
  const [filter, setFilter] = useRuleState("all");
  const [busyId, setBusyId] = useRuleState(null);
  const [tab, setTab] = useRuleState("rules");

  const filtered = useRuleMemo(() => {
    if (filter === "all") return rules;
    return rules.filter(r => r.status === filter);
  }, [rules, filter]);

  const handleSave = async (payload) => {
    const api = window.mossadApi;
    if (editing && editing.id) {
      await api.updateRule(editing.id, payload);
    } else {
      await api.createRule(payload);
    }
    await data.refresh();
    setEditing(null);
  };

  const setStatus = async (rule, status) => {
    setBusyId(rule.id);
    try {
      await window.mossadApi.updateRule(rule.id, { status });
      await data.refresh();
    } catch (err) {
      alert("Failed to update rule: " + err.message);
    } finally {
      setBusyId(null);
    }
  };

  const removeRule = async (rule) => {
    if (!confirm(`Delete rule "${rule.name}"? This cannot be undone.`)) return;
    setBusyId(rule.id);
    try {
      await window.mossadApi.deleteRule(rule.id);
      await data.refresh();
    } catch (err) {
      alert("Failed to delete rule: " + err.message);
    } finally {
      setBusyId(null);
    }
  };

  if (editing) {
    return (
      <div style={{ padding: 18, overflow: "auto", flex: 1 }}>
        <RuleEditor rule={editing === "new" ? null : editing} onSave={handleSave} onCancel={() => setEditing(null)} />
      </div>
    );
  }

  return (
    <div style={{ padding: 18, overflow: "auto", flex: 1 }}>
      <div style={{ display: "flex", alignItems: "center", marginBottom: 16, gap: 10 }}>
        <h1 style={{ margin: 0, fontSize: 22, fontWeight: 600 }}>Rule Settings</h1>
        <div style={{ flex: 1 }} />
        {tab === "rules" && (
          <>
            <select className="field" value={filter} onChange={e => setFilter(e.target.value)} style={{ width: 130 }}>
              <option value="all">All statuses</option>
              <option value="active">Active</option>
              <option value="draft">Draft</option>
              <option value="paused">Paused</option>
              <option value="archived">Archived</option>
            </select>
            <button className="btn primary" onClick={() => setEditing("new")}>
              <Icon.Plus size={11} /> New rule
            </button>
          </>
        )}
      </div>

      <div className="tabs-emph" style={{ display: "flex", gap: 4, borderBottom: "1px solid var(--border)", marginBottom: 16 }}>
        {["rules", "simulation"].map(t => (
          <button key={t} className={`tab ${tab === t ? "active" : ""}`} onClick={() => setTab(t)} style={{ textTransform: "capitalize" }}>
            {t}
          </button>
        ))}
      </div>

      {tab === "simulation" && <SimulationPanel rules={rules} />}

      {tab === "rules" && filtered.length === 0 && (
        <div className="card" style={{ padding: 24, textAlign: "center", color: "var(--fg-3)" }}>
          No rules match the selected filter.
        </div>
      )}

      {tab === "rules" && (
      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(340px, 1fr))", gap: 12 }}>
        {filtered.map(r => (
          <div className="card" key={r.id} style={{ opacity: busyId === r.id ? 0.6 : 1 }}>
            <div style={{ display: "flex", alignItems: "flex-start", gap: 10, marginBottom: 10 }}>
              <div style={{ flex: 1 }}>
                <div style={{ fontWeight: 600, fontSize: 14 }}>{r.name}</div>
                <div style={{ fontSize: 11.5, color: "var(--fg-3)", marginTop: 2 }}>
                  {r.rule_type} · priority {r.priority}
                </div>
              </div>
              <div style={{ display: "flex", gap: 6, alignItems: "center" }}>
                <span className={`pill ${STATUS_PILL[r.status] || r.status}`}>{r.status}</span>
                <span className={`pill ${r.severity === "medium" ? "med" : r.severity}`}>{r.severity}</span>
              </div>
            </div>

            {r.description && (
              <div style={{ fontSize: 12, color: "var(--fg-2)", marginBottom: 10 }}>
                {r.description}
              </div>
            )}

            <div style={{ fontSize: 12, color: "var(--fg-2)", marginBottom: 10, lineHeight: 1.5 }}>
              <span style={{ color: "var(--fg-3)" }}>Triggers when</span> {conditionToSentence(r.condition)}
            </div>

            <div style={{ fontSize: 11.5, color: "var(--fg-3)", marginBottom: 10 }}>
              Lookback: {(Number(r.lookback_seconds) / 86400).toLocaleString(undefined, { maximumFractionDigits: 2 })}d
              {r.aggregation_key ? ` · Aggregate by ${r.aggregation_key}` : ""}
              {r.effective_from ? ` · Effective: ${new Date(r.effective_from).toLocaleString()}` : ""}
              {Array.isArray(r.tags) && r.tags.length > 0 ? ` · ${r.tags.join(", ")}` : ""}
            </div>

            <div style={{ display: "flex", gap: 8, marginTop: 12, flexWrap: "wrap" }}>
              <button className="btn sm" onClick={() => setEditing(r)} disabled={busyId === r.id}>Edit</button>
              {r.status !== "active" && (
                <button className="btn sm success" onClick={() => setStatus(r, "active")} disabled={busyId === r.id}>Activate</button>
              )}
              {r.status === "active" && (
                <button className="btn sm warn" onClick={() => setStatus(r, "paused")} disabled={busyId === r.id}>Pause</button>
              )}
              {r.status !== "archived" && (
                <button className="btn sm" onClick={() => setStatus(r, "archived")} disabled={busyId === r.id}>Archive</button>
              )}
              {r.status === "archived" && (
                <button className="btn sm" onClick={() => setStatus(r, "draft")} disabled={busyId === r.id}>Restore</button>
              )}
              <span style={{ flex: 1 }} />
              <button className="btn sm danger ghost" onClick={() => removeRule(r)} disabled={busyId === r.id}>Delete</button>
            </div>
          </div>
        ))}
      </div>
      )}
    </div>
  );
}

Object.assign(window, { RulesView });
