<?php

declare(strict_types=1);

namespace DoctrineMigrations;

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

final class Version20260401000000 extends AbstractMigration
{
    public function isTransactional(): bool
    {
        return false;
    }

    public function getDescription(): string
    {
        return 'Schéma initial — toutes les entités + extension PostGIS + index spatiaux';
    }

    public function up(Schema $schema): void
    {
        $this->addSql('CREATE EXTENSION IF NOT EXISTS postgis');

        // SargassumObservation
        $this->addSql('
            CREATE TABLE sargassum_observation (
                id UUID NOT NULL DEFAULT gen_random_uuid(),
                geometry geometry(MULTIPOLYGON, 4326) NOT NULL,
                bbox geometry(POLYGON, 4326),
                detected_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
                source VARCHAR(50) NOT NULL,
                tile_id VARCHAR(100) NOT NULL,
                cloud_coverage DOUBLE PRECISION NOT NULL,
                confidence DOUBLE PRECISION NOT NULL,
                afai_mean DOUBLE PRECISION NOT NULL,
                afai_std DOUBLE PRECISION NOT NULL,
                coverage_area DOUBLE PRECISION,
                processing_version VARCHAR(50),
                created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
                PRIMARY KEY(id)
            )
        ');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_observation_detected_at ON sargassum_observation (detected_at)');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_observation_source ON sargassum_observation (source)');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_observation_geometry ON sargassum_observation USING GIST (geometry)');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_observation_bbox ON sargassum_observation USING GIST (bbox)');

        // SargassumForecast
        $this->addSql('
            CREATE TABLE sargassum_forecast (
                id UUID NOT NULL DEFAULT gen_random_uuid(),
                source_observation_id UUID NOT NULL,
                geometry geometry(MULTIPOLYGON, 4326) NOT NULL,
                valid_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
                computed_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
                model_version VARCHAR(50) NOT NULL,
                time_horizon INT NOT NULL,
                confidence DOUBLE PRECISION NOT NULL,
                drift_vector_avg geometry(POINT, 4326),
                created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
                PRIMARY KEY(id)
            )
        ');
        $this->addSql('ALTER TABLE sargassum_forecast ADD CONSTRAINT fk_forecast_observation FOREIGN KEY (source_observation_id) REFERENCES sargassum_observation (id) ON DELETE CASCADE');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_forecast_valid_at ON sargassum_forecast (valid_at)');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_forecast_horizon ON sargassum_forecast (time_horizon)');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_forecast_geometry ON sargassum_forecast USING GIST (geometry)');

        // DataIngestionJob
        $this->addSql('
            CREATE TABLE data_ingestion_job (
                id UUID NOT NULL DEFAULT gen_random_uuid(),
                source VARCHAR(50) NOT NULL,
                tile_id VARCHAR(100) NOT NULL,
                requested_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
                processed_at TIMESTAMP(0) WITHOUT TIME ZONE,
                status VARCHAR(20) NOT NULL DEFAULT \'pending\',
                retry_count INT NOT NULL DEFAULT 0,
                error_message TEXT,
                PRIMARY KEY(id)
            )
        ');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_job_status ON data_ingestion_job (status)');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_job_requested_at ON data_ingestion_job (requested_at)');

        // CoastalPoint
        $this->addSql('
            CREATE TABLE coastal_point (
                id UUID NOT NULL DEFAULT gen_random_uuid(),
                name VARCHAR(150) NOT NULL,
                geometry geometry(POINT, 4326) NOT NULL,
                type VARCHAR(30) NOT NULL,
                region VARCHAR(100) NOT NULL,
                PRIMARY KEY(id)
            )
        ');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_coastal_type ON coastal_point (type)');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_coastal_region ON coastal_point (region)');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_coastal_geometry ON coastal_point USING GIST (geometry)');

        // ImpactScore
        $this->addSql('
            CREATE TABLE impact_score (
                id UUID NOT NULL DEFAULT gen_random_uuid(),
                coastal_point_id UUID NOT NULL,
                timestamp TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
                score INT NOT NULL,
                level VARCHAR(20) NOT NULL,
                distance_to_nearest_sargassum DOUBLE PRECISION,
                density_estimate DOUBLE PRECISION,
                trend VARCHAR(20),
                PRIMARY KEY(id)
            )
        ');
        $this->addSql('ALTER TABLE impact_score ADD CONSTRAINT fk_score_coastal_point FOREIGN KEY (coastal_point_id) REFERENCES coastal_point (id) ON DELETE CASCADE');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_score_timestamp ON impact_score (timestamp)');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_score_level ON impact_score (level)');

        // UserFeedback
        $this->addSql('
            CREATE TABLE user_feedback (
                id UUID NOT NULL DEFAULT gen_random_uuid(),
                coastal_point_id UUID,
                location geometry(POINT, 4326) NOT NULL,
                timestamp TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
                has_seaweed BOOLEAN NOT NULL,
                density VARCHAR(20),
                source VARCHAR(100),
                PRIMARY KEY(id)
            )
        ');
        $this->addSql('ALTER TABLE user_feedback ADD CONSTRAINT fk_feedback_coastal_point FOREIGN KEY (coastal_point_id) REFERENCES coastal_point (id) ON DELETE SET NULL');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_feedback_timestamp ON user_feedback (timestamp)');
        $this->addSql('CREATE INDEX CONCURRENTLY idx_feedback_location ON user_feedback USING GIST (location)');
    }

    public function down(Schema $schema): void
    {
        $this->addSql('ALTER TABLE sargassum_forecast DROP CONSTRAINT fk_forecast_observation');
        $this->addSql('ALTER TABLE impact_score DROP CONSTRAINT fk_score_coastal_point');
        $this->addSql('ALTER TABLE user_feedback DROP CONSTRAINT fk_feedback_coastal_point');

        $this->addSql('DROP TABLE IF EXISTS user_feedback');
        $this->addSql('DROP TABLE IF EXISTS impact_score');
        $this->addSql('DROP TABLE IF EXISTS sargassum_forecast');
        $this->addSql('DROP TABLE IF EXISTS sargassum_observation');
        $this->addSql('DROP TABLE IF EXISTS coastal_point');
        $this->addSql('DROP TABLE IF EXISTS data_ingestion_job');
    }
}
