# Copilot instructions — Bizmart Core 🔧

Summary
- Big picture: Bizmart Core is the shared foundation for the Bizmart ecosystem. It provides common helpers (`includes/shared.php`), an import/job system (`includes/importer.php`), small product utility AJAX handlers in `bizmart-core.php`, and admin pages (e.g., `admin/settings.php`) that call the importer and utilities.

Key files to read first ✅
- `bizmart-core.php` — bootstrapping, small admin AJAX endpoints (product lookups, purchase price API), and asset hooks
- `includes/shared.php` — shared helpers (options, locale helpers, nonce checks, import locks)
- `includes/importer.php` — full importer job lifecycle (preview, start job, scheduling, batch processing, cleanup)
- `admin/settings.php` — UI that wires import flows (calls preview/start/monitor endpoints)

Project-specific conventions & patterns 🧭
- Prefix: `bizmart_` for functions, options, and AJAX actions. Keep this consistent.
- Import jobs:
  - Job storage: option `bizmart_final_import_job` (holds job payload + progress)
  - Locking: transient `bizmart_final_import_lock` via helpers `bizmart_final_import_lock_acquire()` and `bizmart_final_import_lock_release()` — always use these when running jobs.
  - Scheduling: imports run via scheduled hook `bizmart_final_import_job_process` (scheduled with `wp_schedule_single_event`). Avoid re-entrant runs by checking the lock and `wp_next_scheduled()`.
- AJAX handlers: use `add_action('wp_ajax_{action}', ...)` and validate with `bizmart_check_ajax_nonce()` or `wp_verify_nonce()`.
- Admin JS expects `ajaxUrl` and `ajaxNonce` variables — follow the pattern in `admin/settings.php` for naming and usage.

Examples (copy-paste-ready) 📎
- Safe scheduled job start (PHP):
```php
// start job and schedule run
update_option('bizmart_final_import_job', $job_data);
if (!wp_next_scheduled('bizmart_final_import_job_process')) {
  wp_schedule_single_event(time() + 2, 'bizmart_final_import_job_process');
}
```
- Acquire lock inside a long running operation:
```php
$job_id = 'job-' . time();
if (!bizmart_final_import_lock_acquire($job_id, 120)) {
  return; // someone else is running
}
try {
  // do a batch
} finally {
  bizmart_final_import_lock_release($job_id);
}
```
- AJAX handler pattern:
```php
add_action('wp_ajax_bizmart_final_import_preview_items', 'bizmart_final_import_preview_items');
function bizmart_final_import_preview_items() {
  bizmart_check_ajax_nonce();
  $meta_keys = bizmart_final_import_parse_meta_keys($_POST['meta_key'] ?? '');
  // ... respond with wp_send_json_success / wp_send_json_error
}
```

Testing & debugging tips 🐞
- Import debugging: importers use transients and options; inspect `get_option('bizmart_final_import_job')` and `get_transient('bizmart_final_import_lock')` while reproducing.
- Make your scheduled work idempotent and tolerant to partial runs (the importer uses batches and releases locks on errors).
- Use the admin import UI (`admin/settings.php`) as the canonical manual workflow for reproducing end-to-end scenarios.

PR checklist (short)
- Use shared helpers from `includes/shared.php` where applicable instead of re-implementing logic.
- Nonces: verify with `bizmart_check_ajax_nonce()` in AJAX endpoints.
- Jobs: when adding scheduled work, use lock helpers and check `wp_next_scheduled()`.
- Add short manual verification steps in PR description (which admin page to open, sample payloads, expected option/transient states).

Files to reference for more detail
- `includes/importer.php` (job lifecycle)
- `includes/shared.php` (helpers & locking)
- `admin/settings.php` (UI + AJAX usage)
- `bizmart-core.php` (bootstrap & AJAX endpoints)

Feedback
- Anything missing or should I add a short PR template specific to Core (e.g., "Check importer lock/transient and manual import steps")?