<?php

declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

/**
 * Install schema for apexl/io-payment v3.0.1.
 *
 * Gateway-agnostic. Tables:
 *   - payments              — every capture attempt
 *   - payment_logs          — append-only audit
 *   - payment_tokens        — saved card / wallet / bank refs (no PAN)
 *   - payment_webhook_log   — idempotency + replay
 *   - payment_provider_refs — multi-purpose entity-to-gateway-ref map
 *
 * Idempotent: each `CREATE TABLE` is wrapped in `hasTable()` so projects
 * mid-migrating from V1 → V3 (or with pre-existing rows) don't blow up.
 */
final class InstallIoPayment extends AbstractMigration
{
    public function up(): void
    {
        $this->execute('SET FOREIGN_KEY_CHECKS=0');

        if (!$this->hasTable('payments')) {
            $this->execute("CREATE TABLE `payments` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `public_id` varchar(45) NOT NULL,
  `ref` varchar(255) DEFAULT NULL,
  `gateway` varchar(45) NOT NULL,
  `gateway_payment_ref` varchar(255) DEFAULT NULL,
  `gateway_customer_ref` varchar(255) DEFAULT NULL,
  `payment_token_id` int(11) unsigned DEFAULT NULL,
  `amount_cents` int(11) unsigned NOT NULL,
  `amount_refunded_cents` int(11) unsigned NOT NULL DEFAULT 0,
  `currency` varchar(3) NOT NULL DEFAULT 'USD',
  `status` varchar(45) NOT NULL DEFAULT 'pending',
  `failure_code` varchar(100) DEFAULT NULL,
  `failure_message` varchar(500) DEFAULT NULL,
  `remote_order_id` varchar(255) DEFAULT NULL,
  `paid_at` int(11) DEFAULT NULL,
  `refunded_at` int(11) DEFAULT NULL,
  `user_notified` tinyint(1) NOT NULL DEFAULT 0,
  `meta` json DEFAULT NULL,
  `created` int(11) NOT NULL,
  `created_by` int(11) unsigned NOT NULL,
  `modified` int(11) DEFAULT NULL,
  `modified_by` int(11) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `public_id` (`public_id`),
  KEY `gateway` (`gateway`),
  KEY `gateway_payment_ref` (`gateway_payment_ref`),
  KEY `gateway_customer_ref` (`gateway_customer_ref`),
  KEY `status` (`status`),
  KEY `payment_token_id` (`payment_token_id`),
  KEY `ref` (`ref`),
  KEY `remote_order_id` (`remote_order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
        }

        if (!$this->hasTable('payment_logs')) {
            $this->execute("CREATE TABLE `payment_logs` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `payment_id` int(11) unsigned NOT NULL,
  `from_status` varchar(45) NOT NULL,
  `to_status` varchar(45) NOT NULL,
  `source` varchar(45) DEFAULT NULL,
  `reason` varchar(500) DEFAULT NULL,
  `context` json DEFAULT NULL,
  `created` int(11) NOT NULL,
  `created_by` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `payment_id` (`payment_id`),
  KEY `created` (`created`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
        }

        if (!$this->hasTable('payment_tokens')) {
            $this->execute("CREATE TABLE `payment_tokens` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(11) unsigned DEFAULT NULL,
  `consumer_customer_ref` varchar(255) DEFAULT NULL,
  `gateway` varchar(45) NOT NULL,
  `gateway_customer_ref` varchar(255) NOT NULL,
  `gateway_token_ref` varchar(255) NOT NULL,
  `type` varchar(45) NOT NULL DEFAULT 'card',
  `brand` varchar(45) DEFAULT NULL,
  `last4` varchar(4) DEFAULT NULL,
  `exp_month` tinyint(2) unsigned DEFAULT NULL,
  `exp_year` smallint(4) unsigned DEFAULT NULL,
  `is_default` tinyint(1) NOT NULL DEFAULT 0,
  `is_active` tinyint(1) NOT NULL DEFAULT 1,
  `billing_name` varchar(255) DEFAULT NULL,
  `billing_email` varchar(255) DEFAULT NULL,
  `meta` json DEFAULT NULL,
  `created` int(11) NOT NULL,
  `created_by` int(11) unsigned NOT NULL,
  `modified` int(11) DEFAULT NULL,
  `modified_by` int(11) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `gateway_token_ref` (`gateway`, `gateway_token_ref`),
  KEY `user_id` (`user_id`),
  KEY `consumer_customer_ref` (`consumer_customer_ref`),
  KEY `gateway_customer_ref` (`gateway_customer_ref`),
  KEY `is_default` (`is_default`),
  KEY `is_active` (`is_active`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
        }

        if (!$this->hasTable('payment_webhook_log')) {
            $this->execute("CREATE TABLE `payment_webhook_log` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `gateway` varchar(45) NOT NULL,
  `gateway_event_id` varchar(255) NOT NULL,
  `event_type` varchar(100) NOT NULL,
  `gateway_event_type` varchar(100) DEFAULT NULL,
  `occurred_at` int(11) NOT NULL,
  `status` varchar(45) NOT NULL DEFAULT 'received',
  `signature` varchar(500) DEFAULT NULL,
  `failure_reason` varchar(500) DEFAULT NULL,
  `raw_payload` mediumtext NOT NULL,
  `created` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `gateway_event_id` (`gateway`, `gateway_event_id`),
  KEY `gateway` (`gateway`),
  KEY `event_type` (`event_type`),
  KEY `status` (`status`),
  KEY `occurred_at` (`occurred_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
        }

        if (!$this->hasTable('payment_provider_refs')) {
            $this->execute("CREATE TABLE `payment_provider_refs` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `gateway` varchar(45) NOT NULL,
  `entity_type` varchar(255) NOT NULL,
  `entity_id` varchar(64) NOT NULL,
  `gateway_ref` varchar(255) NOT NULL,
  `kind` varchar(45) DEFAULT NULL,
  `is_test` tinyint(1) NOT NULL DEFAULT 0,
  `meta` json DEFAULT NULL,
  `created` int(11) NOT NULL,
  `created_by` int(11) unsigned NOT NULL,
  `modified` int(11) DEFAULT NULL,
  `modified_by` int(11) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `entity_to_gateway` (`entity_type`, `entity_id`, `gateway`, `kind`),
  KEY `gateway_ref` (`gateway`, `gateway_ref`),
  KEY `is_test` (`is_test`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
        }

        $this->execute('SET FOREIGN_KEY_CHECKS=1');
    }

    public function down(): void
    {
        $this->execute('SET FOREIGN_KEY_CHECKS=0');
        $this->execute('DROP TABLE IF EXISTS `payment_provider_refs`');
        $this->execute('DROP TABLE IF EXISTS `payment_webhook_log`');
        $this->execute('DROP TABLE IF EXISTS `payment_tokens`');
        $this->execute('DROP TABLE IF EXISTS `payment_logs`');
        $this->execute('DROP TABLE IF EXISTS `payments`');
        $this->execute('SET FOREIGN_KEY_CHECKS=1');
    }
}
