<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\Migrations\DocStore;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

final class Version20251013094414 extends AbstractMigration
{
    public function getDescription(): string
    {
        return 'DocStore: Enforce filename uniqueness on chill_doc.stored_object_version; clean duplicates and add partial unique index on filename (for new rows only).';
    }

    public function up(Schema $schema): void
    {
        // 1) Clean duplicates: for each (stored_object_id, filename, key, iv), keep only the last inserted row
        //    and delete all others. Use ROW_NUMBER over id DESC to define the last one.
        $this->addSql(<<<'SQL'
            WITH ranked AS (
                SELECT id,
                       rank() OVER (
                           PARTITION BY stored_object_id, filename, "key"::jsonb, iv::jsonb
                           ORDER BY id DESC
                       ) AS rn
                FROM chill_doc.stored_object_version
            )
            DELETE FROM chill_doc.stored_object_version sov
            USING ranked r
            WHERE sov.id = r.id
              AND r.rn > 1
        SQL);

        // 2) Create a partial unique index on filename that applies only to subsequently inserted rows.
        //    Per user's instruction, compute the cutoff using the stored_object_id sequence value.
        $nextVal = (int) $this->connection->fetchOne("SELECT nextval('chill_doc.stored_object_version_id_seq')");

        // Safety: if somehow sequence is not available, fallback to current max id from the table
        if ($nextVal <= 0) {
            $nextVal = (int) $this->connection->fetchOne('SELECT COALESCE(MAX(id), 0) FROM chill_doc.stored_object_version');
        }

        $this->addSql(sprintf(
            'CREATE UNIQUE INDEX chill_doc_stored_object_version_unique_by_filename ON chill_doc.stored_object_version (filename) WHERE id > %d',
            $nextVal
        ));
    }

    public function down(Schema $schema): void
    {
        // Drop the partial unique index; data cleanup is irreversible.
        $this->addSql('DROP INDEX IF EXISTS chill_doc_stored_object_version_unique_by_filename');
    }
}
