"""order refund resource status

Revision ID: 042_refund_resource_status
Revises: 041_system_settings
Create Date: 2026-06-18
"""
import sqlalchemy as sa
from alembic import op


revision = "042_refund_resource_status"
down_revision = "041_system_settings"
branch_labels = None
depends_on = None


def _column_names(bind, table_name: str) -> set[str]:
    return {column["name"] for column in sa.inspect(bind).get_columns(table_name)}


def _index_names(bind, table_name: str) -> set[str]:
    return {index["name"] for index in sa.inspect(bind).get_indexes(table_name)}


def upgrade() -> None:
    bind = op.get_bind()
    tables = set(sa.inspect(bind).get_table_names())
    if "order_refunds" not in tables:
        return

    columns = _column_names(bind, "order_refunds")
    if "resource_status" not in columns:
        op.add_column(
            "order_refunds",
            sa.Column(
                "resource_status",
                sa.String(24),
                nullable=False,
                server_default=sa.text("'none'"),
                comment="none / running / failed / finished / manual_handled / ignored",
            ),
        )
    if "resource_error" not in columns:
        op.add_column("order_refunds", sa.Column("resource_error", sa.Text(), nullable=True))
    if "resource_completed_at" not in columns:
        op.add_column(
            "order_refunds",
            sa.Column("resource_completed_at", sa.DateTime(timezone=True), nullable=True),
        )

    indexes = _index_names(bind, "order_refunds")
    if "ix_order_refunds_resource_status" not in indexes:
        op.create_index("ix_order_refunds_resource_status", "order_refunds", ["resource_status"])

    if "upstream_action_logs" not in tables:
        return

    op.execute(sa.text("""
        UPDATE order_refunds AS r
        SET resource_status = 'finished',
            resource_completed_at = COALESCE(resource_completed_at, CURRENT_TIMESTAMP)
        WHERE EXISTS (
            SELECT 1 FROM upstream_action_logs AS a
            WHERE a.order_refund_id = r.id
              AND a.status IN ('success', 'no_task')
        )
    """))
    op.execute(sa.text("""
        UPDATE order_refunds AS r
        SET resource_status = 'ignored',
            resource_completed_at = COALESCE(resource_completed_at, CURRENT_TIMESTAMP)
        WHERE EXISTS (
            SELECT 1 FROM upstream_action_logs AS a
            WHERE a.order_refund_id = r.id
              AND a.status = 'ignored'
        )
    """))
    op.execute(sa.text("""
        UPDATE order_refunds AS r
        SET resource_status = 'manual_handled',
            resource_completed_at = COALESCE(resource_completed_at, CURRENT_TIMESTAMP)
        WHERE EXISTS (
            SELECT 1 FROM upstream_action_logs AS a
            WHERE a.order_refund_id = r.id
              AND a.status = 'manual_handled'
        )
    """))
    op.execute(sa.text("""
        UPDATE order_refunds AS r
        SET resource_status = 'running',
            resource_completed_at = NULL,
            resource_error = NULL
        WHERE EXISTS (
            SELECT 1 FROM upstream_action_logs AS a
            WHERE a.order_refund_id = r.id
              AND a.status IN ('submitted', 'running')
        )
    """))
    op.execute(sa.text("""
        UPDATE order_refunds AS r
        SET resource_status = 'failed',
            resource_completed_at = COALESCE(resource_completed_at, CURRENT_TIMESTAMP),
            resource_error = (
                SELECT a.error_message FROM upstream_action_logs AS a
                WHERE a.order_refund_id = r.id
                  AND a.status = 'failed'
                  AND a.error_message IS NOT NULL
                ORDER BY a.id DESC
                LIMIT 1
            )
        WHERE EXISTS (
            SELECT 1 FROM upstream_action_logs AS a
            WHERE a.order_refund_id = r.id
              AND a.status = 'failed'
        )
    """))


def downgrade() -> None:
    bind = op.get_bind()
    tables = set(sa.inspect(bind).get_table_names())
    if "order_refunds" not in tables:
        return

    indexes = _index_names(bind, "order_refunds")
    if "ix_order_refunds_resource_status" in indexes:
        op.drop_index("ix_order_refunds_resource_status", table_name="order_refunds")

    columns = _column_names(bind, "order_refunds")
    for column in ("resource_completed_at", "resource_error", "resource_status"):
        if column in columns:
            op.drop_column("order_refunds", column)
