"""Сущность «документ»: описания задач и заметки проектов переносятся в неё,
вложения привязываются к документу вместо задачи (см. docs/TZ.md, модель данных).

Revision ID: d9e8f7c6b5a4
Revises: c8f7e6d5b4a3
Create Date: 2026-09-20
"""

from collections.abc import Sequence

import sqlalchemy as sa

from alembic import op

revision: str = "d9e8f7c6b5a4"
down_revision: str | Sequence[str] | None = "c8f7e6d5b4a3"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
    op.create_table(
        "documents",
        sa.Column("id", sa.Integer(), primary_key=True),
        sa.Column("owner_type", sa.String(length=20), nullable=False),
        sa.Column("owner_id", sa.Integer(), nullable=False),
        sa.Column("body", sa.Text(), nullable=False, server_default=""),
        sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
        sa.UniqueConstraint("owner_type", "owner_id"),
    )
    conn = op.get_bind()
    # Документ заводится каждой задаче и проекту (включая пустой текст) —
    # упрощает код: document всегда есть.
    conn.execute(
        sa.text(
            "INSERT INTO documents (owner_type, owner_id, body, created_at, updated_at) "
            "SELECT 'task', id, description, created_at, created_at FROM tasks"
        )
    )
    conn.execute(
        sa.text(
            "INSERT INTO documents (owner_type, owner_id, body, created_at, updated_at) "
            "SELECT 'project', id, note, created_at, created_at FROM projects"
        )
    )
    op.add_column("attachments", sa.Column("document_id", sa.Integer(), nullable=True))
    conn.execute(
        sa.text(
            "UPDATE attachments SET document_id = ("
            "SELECT id FROM documents WHERE owner_type = 'task' AND owner_id = task_id)"
        )
    )
    op.alter_column("attachments", "document_id", nullable=False)
    op.create_foreign_key(
        "fk_attachments_document_id_documents",
        "attachments",
        "documents",
        ["document_id"],
        ["id"],
        ondelete="CASCADE",
    )
    op.drop_column("attachments", "task_id")
    op.drop_column("tasks", "description")
    op.drop_column("projects", "note")


def downgrade() -> None:
    op.add_column("tasks", sa.Column("description", sa.Text(), nullable=False, server_default=""))
    op.add_column("projects", sa.Column("note", sa.Text(), nullable=False, server_default=""))
    conn = op.get_bind()
    conn.execute(
        sa.text(
            "UPDATE tasks SET description = COALESCE(("
            "SELECT body FROM documents WHERE owner_type = 'task' AND owner_id = tasks.id), '')"
        )
    )
    conn.execute(
        sa.text(
            "UPDATE projects SET note = COALESCE(("
            "SELECT body FROM documents WHERE owner_type = 'project'"
            " AND owner_id = projects.id), '')"
        )
    )
    op.add_column("attachments", sa.Column("task_id", sa.Integer(), nullable=True))
    conn.execute(
        sa.text(
            "UPDATE attachments SET task_id = ("
            "SELECT owner_id FROM documents WHERE documents.id = attachments.document_id)"
        )
    )
    op.drop_constraint(
        "fk_attachments_document_id_documents", "attachments", type_="foreignkey"
    )
    op.alter_column("attachments", "task_id", nullable=False)
    op.create_foreign_key(
        "fk_attachments_task_id_tasks", "attachments", "tasks", ["task_id"], ["id"],
        ondelete="CASCADE",
    )
    op.drop_column("attachments", "document_id")
    op.drop_table("documents")
