-- ============================================================
-- PAYMENT FLOW HARDENING MIGRATION
-- Date: 2026-02-15
-- Purpose: Add idempotency, audit, and integrity constraints
-- ============================================================

-- 1. CREATE PAYMENTS AUDIT TABLE
-- Stores full webhook payloads for forensic debugging

CREATE TABLE IF NOT EXISTS PaymentAudit (
    ID INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    OrderID INT UNSIGNED NULL,
    PaymentIntentID VARCHAR(64) NULL,
    StripeChargeID VARCHAR(64) NULL,
    StripeEventID VARCHAR(64) NOT NULL,
    EventType VARCHAR(64) NOT NULL,
    AmountCents INT UNSIGNED NULL,
    Currency CHAR(3) NULL DEFAULT 'usd',
    RawPayload MEDIUMTEXT NOT NULL,
    ProcessedAt DATETIME NULL,
    ProcessingResult ENUM('success', 'skipped_duplicate', 'skipped_already_paid', 'error') NOT NULL DEFAULT 'success',
    ErrorMessage TEXT NULL,
    CreatedAt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,

    -- Prevent duplicate event processing
    UNIQUE KEY uk_stripe_event (StripeEventID),

    -- Fast lookups
    INDEX idx_order (OrderID),
    INDEX idx_payment_intent (PaymentIntentID),
    INDEX idx_created (CreatedAt)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;


-- 2. ADD MISSING COLUMNS TO ORDERS TABLE
-- (Run these only if columns don't exist)

-- Add StripePaymentIntentID if it doesn't exist
SET @dbname = 'payfrit_dev';
SET @tablename = 'Orders';
SET @columnname = 'StripePaymentIntentID';
SET @preparedStatement = (
    SELECT IF(
        (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
         WHERE TABLE_SCHEMA = @dbname AND TABLE_NAME = @tablename AND COLUMN_NAME = @columnname) > 0,
        'SELECT 1',
        'ALTER TABLE Orders ADD COLUMN StripePaymentIntentID VARCHAR(64) NULL AFTER PaymentStatus'
    )
);
PREPARE stmt FROM @preparedStatement;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;


-- 3. ADD UNIQUE CONSTRAINT ON StripePaymentIntentID
-- Each PaymentIntent can only pay ONE order

ALTER TABLE Orders
    ADD UNIQUE INDEX uk_stripe_payment_intent (StripePaymentIntentID);

-- Note: If this fails with "Duplicate entry", you have data integrity issues to resolve first


-- 4. ADD AMOUNT VERIFICATION COLUMNS (if not present)
-- Store the expected and actual amounts for verification

SET @columnname = 'ExpectedAmountCents';
SET @preparedStatement = (
    SELECT IF(
        (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
         WHERE TABLE_SCHEMA = @dbname AND TABLE_NAME = @tablename AND COLUMN_NAME = @columnname) > 0,
        'SELECT 1',
        'ALTER TABLE Orders ADD COLUMN ExpectedAmountCents INT UNSIGNED NULL AFTER StripePaymentIntentID'
    )
);
PREPARE stmt FROM @preparedStatement;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @columnname = 'ReceivedAmountCents';
SET @preparedStatement = (
    SELECT IF(
        (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
         WHERE TABLE_SCHEMA = @dbname AND TABLE_NAME = @tablename AND COLUMN_NAME = @columnname) > 0,
        'SELECT 1',
        'ALTER TABLE Orders ADD COLUMN ReceivedAmountCents INT UNSIGNED NULL AFTER ExpectedAmountCents'
    )
);
PREPARE stmt FROM @preparedStatement;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;


-- 5. ADD UNIQUE CONSTRAINT ON WorkPayoutLedgers.StripePaymentIntentID
-- Each PaymentIntent should only be linked to ONE ledger entry

ALTER TABLE WorkPayoutLedgers
    ADD UNIQUE INDEX uk_ledger_payment_intent (StripePaymentIntentID);


-- 6. ADD INDEX FOR FAST WEBHOOK LOOKUPS

ALTER TABLE Orders
    ADD INDEX idx_payment_status (PaymentStatus);

-- ============================================================
-- PRODUCTION (payfrit) - Run the same on production database
-- Replace @dbname = 'payfrit_dev' with @dbname = 'payfrit'
-- ============================================================
