"""cenario de precificacao (rateio ligado/desligado) e calculo tripartido do custeio

Revision ID: ee8588821ee1
Revises: 40787e081910
Create Date: 2026-09-10 10:30:00.000000

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = 'ee8588821ee1'
down_revision: Union[str, None] = '40787e081910'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
    # --- cadastro do Cenario de Precificacao ---
    op.create_table(
        'cenario_precificacao',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('codigo', sa.String(length=20), nullable=False),
        sa.Column('nome', sa.String(length=200), nullable=False),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('codigo'),
    )

    # --- rateio embutido: tabelas de excecao (ausencia = ligado, que e o padrao) ---
    op.create_table(
        'cenario_ambiente_desligado',
        sa.Column('cenario_id', sa.Integer(), nullable=False),
        sa.Column('ambiente_id', sa.Integer(), nullable=False),
        sa.ForeignKeyConstraint(['cenario_id'], ['cenario_precificacao.id'], ),
        sa.ForeignKeyConstraint(['ambiente_id'], ['ambiente.id'], ),
        sa.PrimaryKeyConstraint('cenario_id', 'ambiente_id'),
    )
    op.create_table(
        'cenario_maquina_desligada',
        sa.Column('cenario_id', sa.Integer(), nullable=False),
        sa.Column('maquina_id', sa.Integer(), nullable=False),
        sa.ForeignKeyConstraint(['cenario_id'], ['cenario_precificacao.id'], ),
        sa.ForeignKeyConstraint(['maquina_id'], ['maquina.id'], ),
        sa.PrimaryKeyConstraint('cenario_id', 'maquina_id'),
    )
    op.create_table(
        'cenario_funcionario_desligado',
        sa.Column('cenario_id', sa.Integer(), nullable=False),
        sa.Column('funcionario_id', sa.Integer(), nullable=False),
        sa.ForeignKeyConstraint(['cenario_id'], ['cenario_precificacao.id'], ),
        sa.ForeignKeyConstraint(['funcionario_id'], ['funcionario.id'], ),
        sa.PrimaryKeyConstraint('cenario_id', 'funcionario_id'),
    )

    # backfill: cenario placeholder para execucoes de custeio pre-existentes (rateio 100% ligado,
    # igual ao comportamento de hoje - nenhuma linha nas tabelas de desligados)
    op.execute(
        """
        INSERT INTO cenario_precificacao (codigo, nome)
        SELECT 'CENARIO_BACKFILL', 'Migrado automaticamente (revisar)'
        WHERE EXISTS (SELECT 1 FROM custeio_execucao)
          AND NOT EXISTS (SELECT 1 FROM cenario_precificacao WHERE codigo = 'CENARIO_BACKFILL')
        """
    )

    # --- custeio_execucao: cenario_id + custo_fixo_nao_rateado ---
    op.add_column('custeio_execucao', sa.Column('cenario_id', sa.Integer(), nullable=True))
    op.add_column(
        'custeio_execucao',
        sa.Column('custo_fixo_nao_rateado', sa.Numeric(precision=14, scale=6), nullable=True),
    )
    op.execute(
        """
        UPDATE custeio_execucao
        SET cenario_id = (SELECT id FROM cenario_precificacao WHERE codigo = 'CENARIO_BACKFILL'),
            custo_fixo_nao_rateado = 0
        WHERE cenario_id IS NULL
        """
    )
    op.create_foreign_key(
        'custeio_execucao_cenario_id_fkey', 'custeio_execucao', 'cenario_precificacao', ['cenario_id'], ['id']
    )
    op.alter_column('custeio_execucao', 'cenario_id', nullable=False)
    op.alter_column('custeio_execucao', 'custo_fixo_nao_rateado', nullable=False)

    # --- custeio_produto: custo_variavel_lote + producao/variavel unitario ---
    op.add_column(
        'custeio_produto', sa.Column('custo_variavel_lote', sa.Numeric(precision=14, scale=6), nullable=True)
    )
    op.execute(
        """
        UPDATE custeio_produto
        SET custo_variavel_lote = custo_maquina + custo_ambiente + custo_mao_de_obra + custo_insumos
        WHERE custo_variavel_lote IS NULL
        """
    )
    op.alter_column('custeio_produto', 'custo_variavel_lote', nullable=False)

    op.alter_column('custeio_produto', 'custo_total_unitario', new_column_name='custo_producao_unitario')

    op.add_column(
        'custeio_produto', sa.Column('custo_variavel_unitario', sa.Numeric(precision=14, scale=6), nullable=True)
    )
    op.execute("UPDATE custeio_produto SET custo_variavel_unitario = custo_producao_unitario")
    op.alter_column('custeio_produto', 'custo_variavel_unitario', nullable=False)


def downgrade() -> None:
    op.drop_column('custeio_produto', 'custo_variavel_unitario')
    op.alter_column('custeio_produto', 'custo_producao_unitario', new_column_name='custo_total_unitario')
    op.drop_column('custeio_produto', 'custo_variavel_lote')

    op.drop_constraint('custeio_execucao_cenario_id_fkey', 'custeio_execucao', type_='foreignkey')
    op.drop_column('custeio_execucao', 'custo_fixo_nao_rateado')
    op.drop_column('custeio_execucao', 'cenario_id')

    op.drop_table('cenario_funcionario_desligado')
    op.drop_table('cenario_maquina_desligada')
    op.drop_table('cenario_ambiente_desligado')
    op.drop_table('cenario_precificacao')
