"""schema iniziale

Revision ID: 0001
Revises:
Create Date: 2026-04-28 12:40:08.000000

"""
from typing import Sequence, Union
from alembic import op

revision: str = "0001"
down_revision: Union[str, None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
    op.execute("""
        DO $$ BEGIN
            CREATE TYPE userrole AS ENUM ('venditore','valutatore','backoffice','operatore_perizie','approvatore_perizie','admin');
        EXCEPTION WHEN duplicate_object THEN NULL; END $$;

        DO $$ BEGIN
            CREATE TYPE valuationstatus AS ENUM ('bozza','inviata','in_lavorazione','completata','vinta','persa');
        EXCEPTION WHEN duplicate_object THEN NULL; END $$;

        DO $$ BEGIN
            CREATE TYPE valuationpriority AS ENUM ('contratto','preventivo','valutazione');
        EXCEPTION WHEN duplicate_object THEN NULL; END $$;

        DO $$ BEGIN
            CREATE TYPE retakeregime AS ENUM ('nuovo','usato');
        EXCEPTION WHEN duplicate_object THEN NULL; END $$;

        DO $$ BEGIN
            CREATE TYPE repairstatus AS ENUM ('bozza','inviata','in_approvazione','approvata','rifiutata','chiusa');
        EXCEPTION WHEN duplicate_object THEN NULL; END $$;

        DO $$ BEGIN
            CREATE TYPE repairdestination AS ENUM ('vendita','rottamazione','altro');
        EXCEPTION WHEN duplicate_object THEN NULL; END $$;

        DO $$ BEGIN
            CREATE TYPE offerstatus AS ENUM ('in_attesa','accettata','rifiutata');
        EXCEPTION WHEN duplicate_object THEN NULL; END $$;

        CREATE TABLE IF NOT EXISTS groups (
            id SERIAL PRIMARY KEY,
            name VARCHAR(100) NOT NULL,
            description VARCHAR(255),
            is_active BOOLEAN NOT NULL DEFAULT TRUE,
            created_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );

        CREATE TABLE IF NOT EXISTS users (
            id SERIAL PRIMARY KEY,
            email VARCHAR(255) NOT NULL UNIQUE,
            full_name VARCHAR(200) NOT NULL,
            hashed_password VARCHAR(255) NOT NULL,
            role userrole NOT NULL,
            group_id INTEGER REFERENCES groups(id),
            is_active BOOLEAN NOT NULL DEFAULT TRUE,
            notify_email BOOLEAN NOT NULL DEFAULT TRUE,
            notify_push BOOLEAN NOT NULL DEFAULT TRUE,
            created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
            updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );
        CREATE INDEX IF NOT EXISTS ix_users_email ON users (email);

        CREATE TABLE IF NOT EXISTS vehicle_registry (
            plate VARCHAR(10) PRIMARY KEY,
            vin VARCHAR(17),
            vehicle_type VARCHAR(50),
            registration_date DATE,
            homologation_code VARCHAR(50),
            engine_code VARCHAR(20),
            last_revision_date DATE,
            foreign_plate VARCHAR(20),
            foreign_registration_date DATE,
            foreign_country VARCHAR(50),
            is_foreign_registered BOOLEAN,
            source VARCHAR(20),
            raw_response JSONB,
            fetched_at TIMESTAMPTZ,
            expires_at TIMESTAMPTZ,
            selected_motornet_code VARCHAR(20)
        );

        CREATE TABLE IF NOT EXISTS vehicle_versions (
            motornet_code VARCHAR(20) PRIMARY KEY,
            brand_acronym VARCHAR(10),
            brand_name VARCHAR(50),
            model_code VARCHAR(10),
            model_description VARCHAR(100),
            gamma_code VARCHAR(10),
            gamma_description VARCHAR(100),
            series_code VARCHAR(10),
            series_description VARCHAR(100),
            historical_group_code VARCHAR(10),
            historical_group_desc VARCHAR(100),
            cod_desc_model_code VARCHAR(10),
            cod_desc_model_desc VARCHAR(100),
            version_label VARCHAR(200),
            body_type VARCHAR(10),
            doors SMALLINT,
            wheelbase SMALLINT,
            list_price NUMERIC(10,2),
            production_start DATE,
            production_end DATE,
            commercial_start DATE,
            commercial_end DATE,
            first_seen_at TIMESTAMPTZ,
            last_seen_at TIMESTAMPTZ,
            seen_count INTEGER NOT NULL DEFAULT 1,
            source VARCHAR(20)
        );

        CREATE TABLE IF NOT EXISTS plate_version_candidates (
            plate VARCHAR(10) REFERENCES vehicle_registry(plate),
            motornet_code VARCHAR(20) REFERENCES vehicle_versions(motornet_code),
            is_selected BOOLEAN NOT NULL DEFAULT FALSE,
            PRIMARY KEY (plate, motornet_code)
        );

        CREATE TABLE IF NOT EXISTS api_usage_log (
            id SERIAL PRIMARY KEY,
            source VARCHAR(20),
            plate VARCHAR(10),
            hit_cache BOOLEAN NOT NULL DEFAULT FALSE,
            remaining_queries INTEGER,
            called_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );

        CREATE TABLE IF NOT EXISTS valuations (
            id SERIAL PRIMARY KEY,
            plate VARCHAR(10) NOT NULL REFERENCES vehicle_registry(plate),
            user_id INTEGER NOT NULL REFERENCES users(id),
            group_id INTEGER REFERENCES groups(id),
            motornet_code VARCHAR(20) REFERENCES vehicle_versions(motornet_code),
            mileage INTEGER,
            retake_regime retakeregime,
            expected_return_date DATE,
            interest_fuel VARCHAR(50),
            priority valuationpriority NOT NULL DEFAULT 'valutazione',
            notes TEXT,
            status valuationstatus NOT NULL DEFAULT 'bozza',
            final_value NUMERIC(10,2),
            evaluator_id INTEGER REFERENCES users(id),
            evaluator_notes TEXT,
            is_frozen BOOLEAN NOT NULL DEFAULT FALSE,
            priority_rank INTEGER NOT NULL DEFAULT 3,
            created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
            updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );
        CREATE INDEX IF NOT EXISTS ix_valuations_plate ON valuations (plate);
        CREATE INDEX IF NOT EXISTS ix_valuations_status ON valuations (status);

        CREATE TABLE IF NOT EXISTS valuation_photos (
            id SERIAL PRIMARY KEY,
            valuation_id INTEGER NOT NULL REFERENCES valuations(id),
            filename VARCHAR(255) NOT NULL,
            storage_path VARCHAR(500) NOT NULL,
            uploaded_by INTEGER NOT NULL REFERENCES users(id),
            uploaded_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );

        CREATE TABLE IF NOT EXISTS valuation_comments (
            id SERIAL PRIMARY KEY,
            valuation_id INTEGER NOT NULL REFERENCES valuations(id),
            user_id INTEGER NOT NULL REFERENCES users(id),
            content TEXT NOT NULL,
            visible_to_all BOOLEAN NOT NULL DEFAULT TRUE,
            created_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );

        CREATE TABLE IF NOT EXISTS valuation_history (
            id SERIAL PRIMARY KEY,
            valuation_id INTEGER NOT NULL REFERENCES valuations(id),
            changed_by INTEGER NOT NULL REFERENCES users(id),
            field_name VARCHAR(100) NOT NULL,
            old_value TEXT,
            new_value TEXT,
            changed_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );

        CREATE TABLE IF NOT EXISTS contracts (
            id SERIAL PRIMARY KEY,
            contract_number VARCHAR(50) NOT NULL,
            year INTEGER NOT NULL,
            company VARCHAR(100) NOT NULL,
            area VARCHAR(100),
            plate VARCHAR(10),
            customer_name VARCHAR(200),
            import_batch VARCHAR(100),
            imported_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );

        CREATE TABLE IF NOT EXISTS valuation_contracts (
            id SERIAL PRIMARY KEY,
            valuation_id INTEGER NOT NULL REFERENCES valuations(id),
            contract_id INTEGER NOT NULL REFERENCES contracts(id),
            linked_by INTEGER NOT NULL REFERENCES users(id),
            linked_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );

        CREATE TABLE IF NOT EXISTS repairs (
            id SERIAL PRIMARY KEY,
            plate VARCHAR(10) NOT NULL REFERENCES vehicle_registry(plate),
            company VARCHAR(100),
            infinity_repair_number VARCHAR(50),
            intervention_type VARCHAR(100),
            delivery_location VARCHAR(100),
            group_id INTEGER REFERENCES groups(id),
            created_by INTEGER NOT NULL REFERENCES users(id),
            status repairstatus NOT NULL DEFAULT 'bozza',
            destination repairdestination,
            offer_status offerstatus,
            estimated_value NUMERIC(10,2),
            actual_value NUMERIC(10,2),
            subtotal NUMERIC(10,2),
            notes TEXT,
            created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
            updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );
        CREATE INDEX IF NOT EXISTS ix_repairs_plate ON repairs (plate);
        CREATE INDEX IF NOT EXISTS ix_repairs_status ON repairs (status);

        CREATE TABLE IF NOT EXISTS repair_documents (
            id SERIAL PRIMARY KEY,
            repair_id INTEGER NOT NULL REFERENCES repairs(id),
            filename VARCHAR(255) NOT NULL,
            storage_path VARCHAR(500) NOT NULL,
            uploaded_by INTEGER NOT NULL REFERENCES users(id),
            uploaded_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );

        CREATE TABLE IF NOT EXISTS repair_comments (
            id SERIAL PRIMARY KEY,
            repair_id INTEGER NOT NULL REFERENCES repairs(id),
            user_id INTEGER NOT NULL REFERENCES users(id),
            content TEXT NOT NULL,
            mentions TEXT,
            created_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );

        CREATE TABLE IF NOT EXISTS repair_history (
            id SERIAL PRIMARY KEY,
            repair_id INTEGER NOT NULL REFERENCES repairs(id),
            changed_by INTEGER NOT NULL REFERENCES users(id),
            field_name VARCHAR(100) NOT NULL,
            old_value TEXT,
            new_value TEXT,
            changed_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );

        CREATE TABLE IF NOT EXISTS notifications (
            id SERIAL PRIMARY KEY,
            user_id INTEGER NOT NULL REFERENCES users(id),
            title VARCHAR(200) NOT NULL,
            body TEXT,
            link VARCHAR(500),
            is_read BOOLEAN NOT NULL DEFAULT FALSE,
            created_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );

        CREATE TABLE IF NOT EXISTS alert_config (
            id SERIAL PRIMARY KEY,
            key VARCHAR(100) NOT NULL UNIQUE,
            value VARCHAR(255) NOT NULL,
            description VARCHAR(500),
            updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );

        CREATE TABLE IF NOT EXISTS vehicle_stock (
            id SERIAL PRIMARY KEY,
            plate VARCHAR(10) NOT NULL,
            brand VARCHAR(50),
            model VARCHAR(100),
            version VARCHAR(200),
            registration_date VARCHAR(20),
            mileage INTEGER,
            location VARCHAR(100),
            import_batch VARCHAR(100),
            imported_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );
        CREATE INDEX IF NOT EXISTS ix_vehicle_stock_plate ON vehicle_stock (plate);

        CREATE TABLE IF NOT EXISTS repair_costs_avg (
            id SERIAL PRIMARY KEY,
            model VARCHAR(100) NOT NULL,
            avg_cost NUMERIC(10,2),
            import_batch VARCHAR(100),
            imported_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );
        CREATE INDEX IF NOT EXISTS ix_repair_costs_avg_model ON repair_costs_avg (model);

        CREATE TABLE IF NOT EXISTS vehicle_sales_avg (
            id SERIAL PRIMARY KEY,
            model VARCHAR(100) NOT NULL,
            avg_stock_days NUMERIC(6,1),
            avg_repair_cost NUMERIC(10,2),
            avg_margin_eur NUMERIC(10,2),
            avg_margin_pct NUMERIC(5,2),
            avg_sale_price NUMERIC(10,2),
            import_batch VARCHAR(100),
            imported_at TIMESTAMPTZ NOT NULL DEFAULT now()
        );
        CREATE INDEX IF NOT EXISTS ix_vehicle_sales_avg_model ON vehicle_sales_avg (model);

        INSERT INTO alert_config (key, value, description)
        VALUES
            ('cache_ttl_days', '90', 'TTL cache targhe in giorni'),
            ('alert_days_threshold', '30', 'Giorni ritardo rientro per alert'),
            ('repair_alert_pct_consuntiva', '20', 'Soglia % preventivo vs consuntiva'),
            ('repair_alert_pct_preventiva', '20', 'Soglia % preventivo vs preventiva')
        ON CONFLICT (key) DO NOTHING;
    """)


def downgrade() -> None:
    op.execute("""
        DROP TABLE IF EXISTS vehicle_sales_avg CASCADE;
        DROP TABLE IF EXISTS repair_costs_avg CASCADE;
        DROP TABLE IF EXISTS vehicle_stock CASCADE;
        DROP TABLE IF EXISTS alert_config CASCADE;
        DROP TABLE IF EXISTS notifications CASCADE;
        DROP TABLE IF EXISTS repair_history CASCADE;
        DROP TABLE IF EXISTS repair_comments CASCADE;
        DROP TABLE IF EXISTS repair_documents CASCADE;
        DROP TABLE IF EXISTS repairs CASCADE;
        DROP TABLE IF EXISTS valuation_contracts CASCADE;
        DROP TABLE IF EXISTS contracts CASCADE;
        DROP TABLE IF EXISTS valuation_history CASCADE;
        DROP TABLE IF EXISTS valuation_comments CASCADE;
        DROP TABLE IF EXISTS valuation_photos CASCADE;
        DROP TABLE IF EXISTS valuations CASCADE;
        DROP TABLE IF EXISTS api_usage_log CASCADE;
        DROP TABLE IF EXISTS plate_version_candidates CASCADE;
        DROP TABLE IF EXISTS vehicle_versions CASCADE;
        DROP TABLE IF EXISTS vehicle_registry CASCADE;
        DROP TABLE IF EXISTS users CASCADE;
        DROP TABLE IF EXISTS groups CASCADE;
        DROP TYPE IF EXISTS offerstatus;
        DROP TYPE IF EXISTS repairdestination;
        DROP TYPE IF EXISTS repairstatus;
        DROP TYPE IF EXISTS retakeregime;
        DROP TYPE IF EXISTS valuationpriority;
        DROP TYPE IF EXISTS valuationstatus;
        DROP TYPE IF EXISTS userrole;
    """)
