<?php

namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class AddVerificationTokenToCertificateRecords extends Migration
{
    private const INDEX_NAME = 'uniq_certificate_verification_token';

    public function up()
    {
        if (!$this->db->tableExists('certificate_records')) {
            return;
        }

        if (!$this->db->fieldExists('verification_token', 'certificate_records')) {
            $this->forge->addColumn('certificate_records', [
                'verification_token' => [
                    'type'       => 'VARCHAR',
                    'constraint' => 64,
                    'null'       => true,
                    'after'      => 'certificate_number',
                ],
            ]);
        }

        $rows = $this->db->table('certificate_records')
            ->select('id, verification_token')
            ->get()
            ->getResultArray();

        foreach ($rows as $row) {
            if (trim((string)($row['verification_token'] ?? '')) !== '') {
                continue;
            }

            $this->db->table('certificate_records')
                ->where('id', (int)$row['id'])
                ->update(['verification_token' => $this->generateToken()]);
        }

        $this->forge->addUniqueKey('verification_token', self::INDEX_NAME);
        $this->forge->processIndexes('certificate_records');
    }

    public function down()
    {
        if (!$this->db->tableExists('certificate_records')) {
            return;
        }

        if ($this->db->fieldExists('verification_token', 'certificate_records')) {
            $this->forge->dropKey('certificate_records', self::INDEX_NAME);
            $this->forge->dropColumn('certificate_records', 'verification_token');
        }
    }

    private function generateToken(): string
    {
        do {
            $token = bin2hex(random_bytes(16));
            $exists = $this->db->table('certificate_records')
                ->select('id')
                ->where('verification_token', $token)
                ->limit(1)
                ->get()
                ->getRowArray();
        } while ($exists);

        return $token;
    }
}
