<?php

declare(strict_types=1);

namespace DoctrineMigrations;

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

final class Version20260304120000 extends AbstractMigration
{
    public function getDescription(): string
    {
        return 'Remove TypeMachine skeleton system, link custom fields directly to machines';
    }

    public function up(Schema $schema): void
    {
        // 1. Drop requirement FK columns on link tables
        $this->addSql('ALTER TABLE machine_component_links DROP COLUMN IF EXISTS typemachinecomponentrequirementid');
        $this->addSql('ALTER TABLE machine_piece_links DROP COLUMN IF EXISTS typemachinepiecerequirementid');
        $this->addSql('ALTER TABLE machine_product_links DROP COLUMN IF EXISTS typemachineproductrequirementid');

        // 2. Add machineid column to custom_fields (new direct FK to machines)
        $this->addSql('ALTER TABLE custom_fields ADD COLUMN IF NOT EXISTS machineid VARCHAR(36) DEFAULT NULL');
        $this->addSql(<<<'SQL'
            DO $$ BEGIN
              IF NOT EXISTS (
                SELECT 1 FROM information_schema.table_constraints
                WHERE constraint_name = 'fk_custom_fields_machine' AND table_name = 'custom_fields'
              ) THEN
                ALTER TABLE custom_fields ADD CONSTRAINT fk_custom_fields_machine
                  FOREIGN KEY (machineid) REFERENCES machines(id) ON DELETE CASCADE;
              END IF;
            END $$;
            SQL);

        // 3. Enable pgcrypto for gen_random_bytes (needed for CUID generation)
        $this->addSql('CREATE EXTENSION IF NOT EXISTS pgcrypto');

        // 4. Migrate existing custom fields: copy from TypeMachine to each linked Machine
        $this->addSql(<<<'SQL'
            INSERT INTO custom_fields (id, name, type, required, defaultvalue, options, orderindex, machineid, createdat, updatedat)
            SELECT
              'cl' || encode(gen_random_bytes(12), 'hex'),
              cf.name, cf.type, cf.required, cf.defaultvalue, cf.options, cf.orderindex,
              m.id,
              NOW(), NOW()
            FROM custom_fields cf
            JOIN machines m ON m.typemachineid = cf.typemachineid
            WHERE cf.typemachineid IS NOT NULL
            AND NOT EXISTS (
              SELECT 1 FROM custom_fields existing
              WHERE existing.machineid = m.id AND existing.name = cf.name
            )
            SQL);

        // 4. Delete original TypeMachine-linked custom fields (now migrated)
        $this->addSql('DELETE FROM custom_fields WHERE typemachineid IS NOT NULL');

        // 5. Drop typemachineid column from custom_fields
        $this->addSql('ALTER TABLE custom_fields DROP COLUMN IF EXISTS typemachineid');

        // 6. Drop typemachineid column from machines
        $this->addSql('ALTER TABLE machines DROP COLUMN IF EXISTS typemachineid');

        // 7. Drop requirement tables (order matters: these reference type_machines)
        $this->addSql('DROP TABLE IF EXISTS type_machine_component_requirements');
        $this->addSql('DROP TABLE IF EXISTS type_machine_piece_requirements');
        $this->addSql('DROP TABLE IF EXISTS type_machine_product_requirements');

        // 8. Drop type_machines table
        $this->addSql('DROP TABLE IF EXISTS type_machines');
    }

    public function down(Schema $schema): void
    {
        // Recreate type_machines table
        $this->addSql(<<<'SQL'
            CREATE TABLE IF NOT EXISTS type_machines (
                id VARCHAR(36) NOT NULL PRIMARY KEY,
                name VARCHAR(255) NOT NULL UNIQUE,
                description TEXT DEFAULT NULL,
                category VARCHAR(255) DEFAULT NULL,
                maintenancefrequency VARCHAR(255) DEFAULT NULL,
                components JSON DEFAULT NULL,
                criticalparts JSON DEFAULT NULL,
                machinepieces JSON DEFAULT NULL,
                specifications JSON DEFAULT NULL,
                createdat TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
                updatedat TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL
            )
            SQL);

        // Recreate requirement tables
        $this->addSql(<<<'SQL'
            CREATE TABLE IF NOT EXISTS type_machine_component_requirements (
                id VARCHAR(36) NOT NULL PRIMARY KEY,
                typemachineid VARCHAR(36) NOT NULL REFERENCES type_machines(id) ON DELETE CASCADE,
                typecomposantid VARCHAR(36) NOT NULL REFERENCES model_types(id),
                label VARCHAR(255) DEFAULT NULL,
                mincount INTEGER DEFAULT 1,
                maxcount INTEGER DEFAULT NULL,
                required BOOLEAN DEFAULT true,
                allownewmodels BOOLEAN DEFAULT true,
                orderindex INTEGER DEFAULT 0,
                createdat TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
                updatedat TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL
            )
            SQL);

        $this->addSql(<<<'SQL'
            CREATE TABLE IF NOT EXISTS type_machine_piece_requirements (
                id VARCHAR(36) NOT NULL PRIMARY KEY,
                typemachineid VARCHAR(36) NOT NULL REFERENCES type_machines(id) ON DELETE CASCADE,
                typepieceid VARCHAR(36) NOT NULL REFERENCES model_types(id),
                label VARCHAR(255) DEFAULT NULL,
                mincount INTEGER DEFAULT 0,
                maxcount INTEGER DEFAULT NULL,
                required BOOLEAN DEFAULT false,
                allownewmodels BOOLEAN DEFAULT true,
                orderindex INTEGER DEFAULT 0,
                createdat TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
                updatedat TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL
            )
            SQL);

        $this->addSql(<<<'SQL'
            CREATE TABLE IF NOT EXISTS type_machine_product_requirements (
                id VARCHAR(36) NOT NULL PRIMARY KEY,
                typemachineid VARCHAR(36) NOT NULL REFERENCES type_machines(id) ON DELETE CASCADE,
                typeproductid VARCHAR(36) NOT NULL REFERENCES model_types(id),
                label VARCHAR(255) DEFAULT NULL,
                mincount INTEGER DEFAULT 0,
                maxcount INTEGER DEFAULT NULL,
                required BOOLEAN DEFAULT false,
                allownewmodels BOOLEAN DEFAULT true,
                orderindex INTEGER DEFAULT 0,
                createdat TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
                updatedat TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL
            )
            SQL);

        // Re-add typemachineid to machines
        $this->addSql('ALTER TABLE machines ADD COLUMN IF NOT EXISTS typemachineid VARCHAR(36) DEFAULT NULL');

        // Re-add typemachineid to custom_fields
        $this->addSql('ALTER TABLE custom_fields ADD COLUMN IF NOT EXISTS typemachineid VARCHAR(36) DEFAULT NULL');

        // Re-add requirement FK columns to link tables
        $this->addSql('ALTER TABLE machine_component_links ADD COLUMN IF NOT EXISTS typemachinecomponentrequirementid VARCHAR(36) DEFAULT NULL');
        $this->addSql('ALTER TABLE machine_piece_links ADD COLUMN IF NOT EXISTS typemachinepiecerequirementid VARCHAR(36) DEFAULT NULL');
        $this->addSql('ALTER TABLE machine_product_links ADD COLUMN IF NOT EXISTS typemachineproductrequirementid VARCHAR(36) DEFAULT NULL');

        // Drop machine FK on custom_fields
        $this->addSql('ALTER TABLE custom_fields DROP COLUMN IF EXISTS machineid');
    }
}
