-- ============================================================
--  Buy Local Lowveld — Phase 2b schema additions
-- ============================================================
--
--  ADDITIVE migration on top of schema.sql (Phase 2a).
--  Safe to run against a populated Phase 2a database.
--
-- ============================================================

SET NAMES utf8mb4;

-- ------------------------------------------------------------
-- Payments log
-- ------------------------------------------------------------
-- One row per ITN received from PayFast. Gives us full audit +
-- idempotency (pf_payment_id is unique so replays are no-ops).
DROP TABLE IF EXISTS payments;
CREATE TABLE payments (
    id                INT UNSIGNED NOT NULL AUTO_INCREMENT,
    member_id         INT UNSIGNED DEFAULT NULL,
    invoice_id        INT UNSIGNED DEFAULT NULL,
    order_id          INT UNSIGNED DEFAULT NULL,
    gateway           VARCHAR(40)  NOT NULL DEFAULT 'payfast',
    pf_payment_id     VARCHAR(100) DEFAULT NULL,
    pf_token          VARCHAR(100) DEFAULT NULL,
    payment_status    VARCHAR(40)  DEFAULT NULL,            -- COMPLETE / CANCELLED / FAILED
    amount_gross_cents INT         NOT NULL,
    amount_fee_cents   INT         DEFAULT 0,
    amount_net_cents   INT         DEFAULT 0,
    m_payment_id      VARCHAR(100) DEFAULT NULL,            -- our side reference
    raw_payload       MEDIUMTEXT   DEFAULT NULL,            -- full ITN post for debugging
    signature_ok      TINYINT(1)   NOT NULL DEFAULT 0,
    ip_ok             TINYINT(1)   NOT NULL DEFAULT 0,
    processed         TINYINT(1)   NOT NULL DEFAULT 0,
    created_at        DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    UNIQUE KEY uq_payments_pfid (pf_payment_id),
    KEY idx_payments_invoice (invoice_id),
    KEY idx_payments_member  (member_id),
    CONSTRAINT fk_payments_member  FOREIGN KEY (member_id)  REFERENCES members(id)  ON DELETE SET NULL,
    CONSTRAINT fk_payments_invoice FOREIGN KEY (invoice_id) REFERENCES invoices(id) ON DELETE SET NULL,
    CONSTRAINT fk_payments_order   FOREIGN KEY (order_id)   REFERENCES orders(id)   ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- ------------------------------------------------------------
-- Subscription tokens (PayFast "tokenisation" for recurring)
-- ------------------------------------------------------------
DROP TABLE IF EXISTS payment_tokens;
CREATE TABLE payment_tokens (
    id             INT UNSIGNED NOT NULL AUTO_INCREMENT,
    member_id      INT UNSIGNED NOT NULL,
    gateway        VARCHAR(40)  NOT NULL DEFAULT 'payfast',
    token          VARCHAR(100) NOT NULL,                   -- PayFast token UUID
    purpose        ENUM('membership','general') NOT NULL DEFAULT 'membership',
    status         ENUM('active','cancelled','failed')      NOT NULL DEFAULT 'active',
    next_charge_at DATE         DEFAULT NULL,
    last_charge_at DATETIME     DEFAULT NULL,
    created_at     DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP,
    cancelled_at   DATETIME     DEFAULT NULL,
    PRIMARY KEY (id),
    UNIQUE KEY uq_tokens_token (token),
    KEY idx_tokens_member (member_id),
    CONSTRAINT fk_tokens_member FOREIGN KEY (member_id) REFERENCES members(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- ------------------------------------------------------------
-- Cron run log
-- ------------------------------------------------------------
-- Every invocation of a cron script writes one row here.
-- Admins can see when each job last ran and how many rows it touched.
DROP TABLE IF EXISTS cron_runs;
CREATE TABLE cron_runs (
    id          INT UNSIGNED NOT NULL AUTO_INCREMENT,
    job_name    VARCHAR(80)  NOT NULL,
    started_at  DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP,
    finished_at DATETIME     DEFAULT NULL,
    rows_processed INT       DEFAULT 0,
    outcome     ENUM('running','ok','partial','failed') NOT NULL DEFAULT 'running',
    detail      TEXT         DEFAULT NULL,
    PRIMARY KEY (id),
    KEY idx_cron_job (job_name),
    KEY idx_cron_started (started_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- ------------------------------------------------------------
-- Rate limit buckets
-- ------------------------------------------------------------
-- Simple counter per (key, window). The window is a rounded time
-- like "2026-04-21 14:00". `key_hash` is SHA-256(purpose + ip) so
-- we don't store raw IPs in plaintext.
DROP TABLE IF EXISTS rate_limits;
CREATE TABLE rate_limits (
    key_hash    CHAR(64)     NOT NULL,
    window_key  VARCHAR(40)  NOT NULL,          -- e.g. "login:2026-04-21 14:00"
    hits        INT UNSIGNED NOT NULL DEFAULT 1,
    updated_at  DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (key_hash, window_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
