=== Doctor Subs ===
Contributors: davidrukahu
Tags: woocommerce, subscriptions, troubleshooting, diagnostics, payment issues
Requires at least: 6.4
Tested up to: 6.9
Requires PHP: 7.4
Stable tag: 2.1.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Spot the broken WooCommerce subscriptions you didn't know about, and fix them with one click you can undo.

== Description ==

You don't always find out a renewal is broken until a customer emails you. Doctor Subs watches your subscriptions in the background and tells you when something is silently wrong, before you hear about it.

For each problem, you get a plain-English explanation, a preview of exactly what the fix will change, and one button to apply it. Every fix is logged and can be undone. If a fix already triggered a real payment, the undo screen says so explicitly.

Built for store owners who run between 20 and 500 active subscriptions and don't want to read logs or write code.

= What it spots =

* Subscriptions silently flipped to "manual renewal" by recent WooCommerce bugs, so auto-billing has quietly stopped.
* Active subscriptions with no next payment scheduled - the next charge will never happen.
* A wave of subscriptions all going on hold at once after a product change.
* Customers who paid in Stripe but whose subscription is still showing on hold.
* Subscriptions with a couple of recent failed payments - usually a gateway blip a single retry fixes.
* Subscription totals that no longer match their line items.

= What it doesn't do =

* It doesn't change anything without you clicking. There's no auto-fix.
* It doesn't replace dunning, retries, or refunds. For card declines and refunds, use your gateway.
* It doesn't send your customer data anywhere.

If you've ever found out about a broken renewal from a customer instead of from your store, this is for you.

== Installation ==

= Automatic =

1. Plugins > Add New > search "Doctor Subs"
2. Install > Activate

= Manual =

1. Download the plugin zip from WordPress.org or GitHub Releases
2. Plugins > Add New > Upload Plugin
3. Install > Activate

= After activation =

1. WooCommerce > Doctor Subs
2. Click **Scan my subscriptions**
3. Review the X-of-Y healthy stat and the two action counters, click into the broken bucket, preview a fix, commit

== Frequently Asked Questions ==

= Does Doctor Subs fix issues automatically? =

No. The plugin never mutates your data without an explicit Fix click. Every change shows a preview first and lands in the Fix history with a Revert button. The scanner only detects; the merchant decides.

= What happens if I revert a fix after the payment already ran? =

The revert confirm explicitly tells you: the re-scheduled payment has already charged the customer, reverting will undo the status change but will NOT refund. If a refund is needed, handle it in the related WooCommerce order.

= Does it really detect the silent "manual renewal" bug? =

Yes. The Manual-renewal drift rule looks for active subs whose `_requires_manual_renewal` flag is set despite a working Stripe customer/source meta on file. It clears the flag in both the orders table and postmeta (belt-and-braces against the HPOS sync gap), re-stamps `next_payment` if past-due, and schedules a fresh renewal so WCS bills automatically again.

= Is this a replacement for dunning management? =

No. Doctor Subs fixes structural issues (missing AS events, stuck-on-hold statuses, manual-renewal flag drift, line-item total drift). It does not handle card declines, SCA prompts, or retry strategy. For those, use your gateway's built-in dunning or a dedicated plugin.

= Which gateways does it support? =

v2.1: Stripe fully supported across all rules that need a gateway signal (stuck on-hold, manual-renewal drift). The remaining rules are gateway-agnostic. PayPal, Authorize.net, Square, and WooPayments variants land in a future release.

= Will it work on stores with 10,000+ subscriptions? =

Yes. The scanner uses a shared pre-built index so every rule is O(1) per sub (no N+1 queries). The `DR_SUBS_SCAN_BATCH_SIZE` constant lets you tune the batch size in wp-config.php for very large stores.

= Can I extend it with my own rules? =

Yes. Implement `DR_Subs_Rule_Interface` and register on the `dr_subs_register_rules` action. See the six built-in rules under `includes/rules/` for examples.

= Is HPOS supported? =

Required. Doctor Subs declares High-Performance Order Storage compatibility and requires WooCommerce 9.0 or higher.

= How is this different from WooCommerce's built-in Subscriptions Health Check tool? =

WooCommerce ships a [Subscriptions Health Check tool](https://woocommerce.com/document/woocommerce-subscriptions-health-check/) that flags two conditions: subs on manual renewal that have a valid saved payment token, and subs with a missing or overdue next-payment date. It surfaces them as a list and points you at the relevant order so you can act manually.

Doctor Subs overlaps on those two patterns (Manual-renewal drift, Ghost subscription) and adds four more the built-in tool doesn't cover: mass on-hold cascade after a product edit, stuck on-hold despite a captured Stripe renewal, repeated payment failures within 30 days, and total drift between the stored total and line items.

It also wraps every detection in a preview-before-apply modal, one-click fixes, a per-entry revert journal, bulk-fix across N matches, state-guarded apply (aborts if the sub changed between detection and apply), and an optional email digest when something new breaks between scans.

Short version: WC's tool is a flagger. Doctor Subs is a flagger plus a reversible repair surface. Running both is fine - they don't conflict.

== Screenshots ==

1. Dashboard: X-of-Y healthy stat, At risk + Broken counters, search, rule chips, and the Needs attention table with the "Fix all" CTA next to the active filter
2. Fix preview modal: plain-English narrative, named diff (before -> after), and the "you can undo this" reassurance line
3. Fix history: per-rule filter chips along the top, plain-English summary per row, individual Revert buttons
4. Settings: alerts toggle + email recipient, fix-history retention selector, anonymous telemetry opt-in
5. Detection rules: six rule cards with on/off toggles plus Detects + Fix descriptions for every rule

== Changelog ==

= 2.1.1 =

Docs only. New FAQ entry comparing Doctor Subs to WooCommerce's built-in Subscriptions Health Check tool, with link to the official WooCommerce documentation. No code changes.

= 2.1.0 =

Major detection + UX expansion. Six rules now ship; design language tightened.

**New rules (3):**

* **Manual-renewal drift** (Stripe-only): detects active subs silently flipped to manual renewal despite a Stripe customer/source on file. Direct response to the four April 2026 subscriptions-core bug disclosures. Fix clears the flag in HPOS + postmeta, re-stamps next_payment if past-due, and schedules a fresh renewal.
* **Mass on-hold cascade**: detects 20 or more on-hold transitions for the same product within a 1-hour window. Backed by a new `dr_subs_status_transitions` log written by an observer on every subscription status change. Fix reactivates each cascade member; bulk-fix recovers the whole cascade in one click.
* **Total drift** (flag-only): detects subs whose stored total no longer matches the sum of line items + tax + shipping + fees by more than $0.50, ignoring subs modified in the last 7 days. Surfaces the discrepancy and links to the sub for manual review.

**Dashboard:**

* Healthy counter relocated as an "X of Y healthy" stat above the action counters; can no longer be mistaken for a clickable filter.
* Search bar matches sub number, customer name, and billing email. Debounced, ESC clears.
* Rule chip filters above the table; bucket counter and rule chip are now mutually exclusive (clicking one clears the other).
* Reason column strips inline HTML so emphasis tags never render literally.
* Issue column header moved to screen-reader-only; the rule pill carries the label.

**Bulk + revert:**

* Bulk-fix button beside the active rule chip OR in "All rules" mode: groups visible rows by rule, posts one batch per rule, surfaces a styled confirm modal listing the per-rule counts and a renewal-payment warning. Total Drift opts out (manual-only).
* Revert confirm now opens a styled in-plugin modal instead of `window.confirm()`. When the journal entry's AS action has already executed, the modal escalates to a danger-styled button and the explicit "this will NOT refund" warning.

**Settings:**

* New "Detection rules" section listing all six rules with toggle, plain-English Detects/Fix descriptions, and bucket tag. Disabled rules skip detection on every scan.
* Plain-English summaries on dashboard rule chips and table pills via `DR_Subs_Rule_Catalog`.

**Fix history:**

* Plain-English summary per row ("Rescheduled the missed renewal payment", "Reactivated as part of a mass-hold cascade recovery", etc.) instead of the raw `key: value` after-state dump.
* All canonical rule ids now render correct labels (legacy short ids fall back).

**Schema + scanner:**

* Schema bumped to 2.1.0; new `dr_subs_status_transitions` table with `sub_id`, `from_status`, `to_status`, `product_id`, `variation_id`, `transitioned_at`. Pruned daily on a 30-day TTL.
* Scanner now walks `active`, `on-hold`, and `pending-cancel` statuses (was `active` only). Mass-hold + Stuck-on-hold rules now reach their target subs.
* Manual_renewal_drift registered before Ghost_sub so it claims primary-rule on the same broken state with the right fix. Ghost_sub now skips manual-renewal subs entirely.

**Design + accessibility:**

* Display typeface swapped from Instrument Serif to Source Serif 4 (less editorial-romantic, calmer italic).
* Counter numerals dropped from 62px display serif to 32px Switzer 500: a 28-broken count no longer reads like a panic-amplifier.
* Dashboard hint copy de-imperative-d ("needs you now" -> "since last scan").
* All em dashes / en dashes / minus signs replaced with plain hyphens across PHP, JS, CSS, and views.
* Modal focus on open lands on the dialog itself (tabindex=-1) so the sub-id link no longer reads as "selected".
* New `.btn-danger` token using the existing terracotta `--broken` for genuinely destructive actions.

**Internal:**

* New `DR_Subs_Rule_Catalog` central source-of-truth for per-rule label, summary, detect, fix, bucket, and journal_summary copy.
* New `dev/` directory with `seed-test-data.php` and `wipe-test-data.php` (excluded from the production zip via build script + CI workflow).

= 2.0.0-alpha.1 =

Major rewrite. Single breaking change moment: every PHP class renamed from WCST_* to DR_Subs_*; legacy class_alias shims ship for the three most-likely-extended public classes.

* Traffic-light dashboard with per-bucket drill-down
* Three deterministic detection rules: Ghost Sub, On-Hold with Paid Renewal (Stripe), Repeated Payment Failures
* Daily background scanner via Action Scheduler + WP-Cron watchdog
* One-click fixes with state-guarded apply and reversible Fix journal
* Fix preview modal with named diff and executed-payment warning
* Email digest alerts (off by default; configurable recipient)
* Settings page with retention controls and anonymous telemetry opt-in
* 20 language translations via Potomatic
* Self-hosted typography, no external asset fetches
* HPOS baseline (WC 9.0+)

= 1.2.4 =

* Fixed all security issues (sanitization, validation, escaping)
* Fixed Action Scheduler compatibility (scheduled_date_gmt column)
* Improved error handling and debugging
* Enhanced analyzer stability
* Added PHPCS configuration

= 1.2.3 =

* Initial release

== Upgrade Notice ==

= 2.1.1 =

Docs-only release. Adds an FAQ comparing Doctor Subs to WooCommerce's new built-in Subscriptions Health Check tool. No code changes.

= 2.1.0 =

Adds three new detection rules (manual-renewal drift, mass on-hold cascade, total drift), bulk-fix for any visible row set, and a styled revert confirm with executed-payment warnings. Schema migrates automatically on first admin page load. No breaking API changes for third-party rules.

= 2.0.0-alpha.1 =

Major rewrite. Breaking class rename: WCST_* to DR_Subs_*. class_alias shims keep WCST_Plugin / WCST_Admin / WCST_Ajax_Handler working. Backup before upgrading if you have custom integrations.

= 1.2.4 =

Important security fixes and compatibility improvements. All users should upgrade.
