# Copyright 2026 Criptomart
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import logging

_logger = logging.getLogger(__name__)


def migrate(cr, version):
    """Convert JSONB columns to proper types in product_product AND product_template.

    This migration handles the removal of company_dependent=True from fields.
    When company_dependent is removed, Odoo may leave JSONB columns that need
    explicit conversion to proper column types.

    Tables affected:
    - product_product
    - product_template
    """
    if not version:
        return

    _logger.info("Starting migration 18.0.2.5.0: JSONB → proper types conversion")

    # Convert product_product table
    _convert_product_product_columns(cr)

    # Convert product_template table
    _convert_product_template_columns(cr)

    _logger.info("Migration 18.0.2.5.0 completed successfully")


def _convert_product_product_columns(cr):
    """Convert product_product JSONB columns to proper types."""
    _logger.info("Converting product_product JSONB columns...")

    # Check column types
    cr.execute("""
        SELECT column_name, data_type
        FROM information_schema.columns
        WHERE table_name = 'product_product'
        AND column_name IN (
            'last_purchase_price_updated',
            'list_price_theoritical',
            'last_purchase_price_received',
            'last_purchase_price_compute_type'
        )
    """)
    columns = {row[0]: row[1] for row in cr.fetchall()}

    # Convert each JSONB column if needed
    if columns.get("last_purchase_price_updated") == "jsonb":
        _logger.info(
            "Converting product_product.last_purchase_price_updated from JSONB"
        )
        _convert_jsonb_to_boolean(cr, "product_product", "last_purchase_price_updated")

    if columns.get("list_price_theoritical") == "jsonb":
        _logger.info("Converting product_product.list_price_theoritical from JSONB")
        _convert_jsonb_to_numeric(cr, "product_product", "list_price_theoritical")

    if columns.get("last_purchase_price_received") == "jsonb":
        _logger.info(
            "Converting product_product.last_purchase_price_received from JSONB"
        )
        _convert_jsonb_to_numeric(cr, "product_product", "last_purchase_price_received")

    if columns.get("last_purchase_price_compute_type") == "jsonb":
        _logger.info(
            "Converting product_product.last_purchase_price_compute_type from JSONB"
        )
        _convert_jsonb_to_varchar(
            cr, "product_product", "last_purchase_price_compute_type"
        )


def _convert_product_template_columns(cr):
    """Convert product_template JSONB columns to proper types."""
    _logger.info("Converting product_template JSONB columns...")

    # Check column types
    cr.execute("""
        SELECT column_name, data_type
        FROM information_schema.columns
        WHERE table_name = 'product_template'
        AND column_name IN (
            'last_purchase_price_updated',
            'list_price_theoritical',
            'last_purchase_price_received',
            'last_purchase_price_compute_type'
        )
    """)
    columns = {row[0]: row[1] for row in cr.fetchall()}

    # Convert each JSONB column if needed
    if columns.get("last_purchase_price_updated") == "jsonb":
        _logger.info(
            "Converting product_template.last_purchase_price_updated from JSONB"
        )
        _convert_jsonb_to_boolean(cr, "product_template", "last_purchase_price_updated")

    if columns.get("list_price_theoritical") == "jsonb":
        _logger.info("Converting product_template.list_price_theoritical from JSONB")
        _convert_jsonb_to_numeric(cr, "product_template", "list_price_theoritical")

    if columns.get("last_purchase_price_received") == "jsonb":
        _logger.info(
            "Converting product_template.last_purchase_price_received from JSONB"
        )
        _convert_jsonb_to_numeric(
            cr, "product_template", "last_purchase_price_received"
        )

    if columns.get("last_purchase_price_compute_type") == "jsonb":
        _logger.info(
            "Converting product_template.last_purchase_price_compute_type from JSONB"
        )
        _convert_jsonb_to_varchar(
            cr, "product_template", "last_purchase_price_compute_type"
        )


def _convert_jsonb_to_numeric(
    cr, table_name, column_name
):  # pylint: disable=sql-injection
    """Convert a JSONB column to NUMERIC type extracting company value."""
    temp_col = f"{column_name}_new"

    # Create temp NUMERIC column
    cr.execute(f"ALTER TABLE {table_name} ADD COLUMN {temp_col} NUMERIC")

    # Extract value from JSONB (company_id as key)
    cr.execute(f"""
        UPDATE {table_name}
        SET {temp_col} = CAST(
            ({column_name}->>(SELECT jsonb_object_keys({column_name}) LIMIT 1))
            AS NUMERIC
        )
        WHERE {column_name} IS NOT NULL
        AND {column_name}::text != 'null'
        AND {column_name}::text LIKE '{{%'
    """)

    # Drop old JSONB column
    cr.execute(f"ALTER TABLE {table_name} DROP COLUMN {column_name} CASCADE")

    # Rename new column
    cr.execute(f"ALTER TABLE {table_name} RENAME COLUMN {temp_col} TO {column_name}")

    # Set default for NULLs
    cr.execute(
        f"UPDATE {table_name} SET {column_name} = 0.0 WHERE {column_name} IS NULL"
    )

    _logger.info(f"✅ {table_name}.{column_name} converted from JSONB to NUMERIC")


def _convert_jsonb_to_boolean(
    cr, table_name, column_name
):  # pylint: disable=sql-injection
    """Convert a JSONB column to BOOLEAN type extracting company value."""
    temp_col = f"{column_name}_new"

    # Create temp BOOLEAN column
    cr.execute(f"ALTER TABLE {table_name} ADD COLUMN {temp_col} BOOLEAN")

    # Extract value from JSONB
    cr.execute(f"""
        UPDATE {table_name}
        SET {temp_col} = CAST(
            ({column_name}->>(SELECT jsonb_object_keys({column_name}) LIMIT 1))
            AS BOOLEAN
        )
        WHERE {column_name} IS NOT NULL
        AND {column_name}::text != 'null'
        AND {column_name}::text LIKE '{{%'
    """)

    # Drop old JSONB column
    cr.execute(f"ALTER TABLE {table_name} DROP COLUMN {column_name} CASCADE")

    # Rename new column
    cr.execute(f"ALTER TABLE {table_name} RENAME COLUMN {temp_col} TO {column_name}")

    # Set default for NULLs
    cr.execute(
        f"UPDATE {table_name} SET {column_name} = FALSE WHERE {column_name} IS NULL"
    )

    _logger.info(f"✅ {table_name}.{column_name} converted from JSONB to BOOLEAN")


def _convert_jsonb_to_varchar(
    cr, table_name, column_name
):  # pylint: disable=sql-injection
    """Convert a JSONB column to VARCHAR type extracting company value."""
    temp_col = f"{column_name}_new"

    # Create temp VARCHAR column
    cr.execute(f"ALTER TABLE {table_name} ADD COLUMN {temp_col} VARCHAR")

    # Extract value from JSONB
    cr.execute(f"""
        UPDATE {table_name}
        SET {temp_col} = {column_name}->>(SELECT jsonb_object_keys({column_name}) LIMIT 1)
        WHERE {column_name} IS NOT NULL
        AND {column_name}::text != 'null'
        AND {column_name}::text LIKE '{{%'
    """)

    # Drop old JSONB column
    cr.execute(f"ALTER TABLE {table_name} DROP COLUMN {column_name} CASCADE")

    # Rename new column
    cr.execute(f"ALTER TABLE {table_name} RENAME COLUMN {temp_col} TO {column_name}")

    # Set default for NULLs
    cr.execute(
        f"UPDATE {table_name} SET {column_name} = 'without_discounts' WHERE {column_name} IS NULL"
    )

    _logger.info(f"✅ {table_name}.{column_name} converted from JSONB to VARCHAR")
