<?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\Person;

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

/**
 * Add fullnameCanonical column for trigram matching (fast searching).
 */
final class Version20181023101621 extends AbstractMigration
{
    public function down(Schema $schema): void
    {
        $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.');

        $this->addSql('DROP INDEX fullnameCanonical_trgm_idx');
        $this->addSql('ALTER TABLE chill_person_person DROP fullnameCanonical');
        $this->addSql('DROP TRIGGER canonicalize_fullname_on_update ON chill_person_person');
        $this->addSql('DROP FUNCTION canonicalize_fullname_on_update()');
        $this->addSql('DROP TRIGGER canonicalize_fullname_on_insert ON chill_person_person');
        $this->addSql('DROP FUNCTION canonicalize_fullname_on_insert()');
    }

    public function up(Schema $schema): void
    {
        $this->abortIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.');

        $this->addSql("ALTER TABLE chill_person_person ADD fullnameCanonical VARCHAR(255) DEFAULT '' ");
        $this->addSql("UPDATE chill_person_person SET fullnameCanonical=LOWER(UNACCENT(CONCAT(firstname, ' ', lastname)))");
        $this->addSql('CREATE INDEX fullnameCanonical_trgm_idx ON chill_person_person USING GIN (fullnameCanonical gin_trgm_ops)');

        $this->addSql(
            <<<'SQL_WRAP'
            CREATE OR REPLACE FUNCTION canonicalize_fullname_on_update() RETURNS TRIGGER AS
            $BODY$
            BEGIN
                IF NEW.firstname <> OLD.firstname OR NEW.lastname <> OLD.lastname
                THEN
                   UPDATE chill_person_person
                   SET fullnameCanonical=LOWER(UNACCENT(CONCAT(NEW.firstname, ' ', NEW.lastname)))
                   WHERE id=NEW.id;
                END IF;
                RETURN NEW;
            END;
            $BODY$ LANGUAGE PLPGSQL;
SQL_WRAP
        );
        $this->addSql(
            <<<'SQL'
                            CREATE TRIGGER canonicalize_fullname_on_update
                            AFTER UPDATE
                            ON chill_person_person
                            FOR EACH ROW
                            WHEN (pg_trigger_depth() = 0)
                            EXECUTE PROCEDURE canonicalize_fullname_on_update();
                SQL
        );

        $this->addSql(
            <<<'SQL_WRAP'
            CREATE OR REPLACE FUNCTION canonicalize_fullname_on_insert() RETURNS TRIGGER AS
            $BODY$
            BEGIN
                UPDATE chill_person_person
                SET fullnameCanonical=LOWER(UNACCENT(CONCAT(NEW.firstname, ' ', NEW.lastname)))
                WHERE id=NEW.id;
                RETURN NEW;
            END;
            $BODY$ LANGUAGE PLPGSQL;
SQL_WRAP
        );
        $this->addSql(
            <<<'SQL'
                            CREATE TRIGGER canonicalize_fullname_on_insert
                            AFTER INSERT
                            ON chill_person_person
                            FOR EACH ROW
                            EXECUTE PROCEDURE canonicalize_fullname_on_insert();
                SQL
        );
    }
}
