from collections.abc import Collection, Sequence
from typing import Any

from django.db.migrations.operations.base import Operation
from django.db.models.constraints import BaseConstraint
from django.db.models.fields import Field
from django.db.models.indexes import Index
from django.db.models.manager import Manager

class ModelOperation(Operation):
    name: str = ...
    def __init__(self, name: str) -> None: ...
    def name_lower(self) -> str: ...

class CreateModel(ModelOperation):
    fields: Sequence[tuple[str, Field[Any, Any]]] = ...
    options: Any = ...
    bases: Sequence[type | str] | None = ...
    managers: Sequence[tuple[str, Manager[Any]]] | None = ...
    def __init__(
        self,
        name: str,
        fields: Sequence[tuple[str, Field[Any, Any]]],
        options: dict[str, Any] | None = ...,
        bases: Sequence[type | str] | None = ...,
        managers: Sequence[tuple[str, Manager[Any]]] | None = ...,
    ) -> None: ...
    def model_to_key(self, model: str) -> list[str]: ...

class DeleteModel(ModelOperation): ...

class RenameModel(ModelOperation):
    old_name: Any = ...
    new_name: Any = ...
    def __init__(self, old_name: str, new_name: str) -> None: ...
    def old_name_lower(self) -> str: ...
    def new_name_lower(self) -> str: ...

class AlterModelTable(ModelOperation):
    table: str | None = ...
    def __init__(self, name: str, table: str | None) -> None: ...

class ModelOptionOperation(ModelOperation): ...
class FieldRelatedOptionOperation(ModelOptionOperation): ...

class AlterUniqueTogether(FieldRelatedOptionOperation):
    option_name: str = ...
    unique_together: Collection[Sequence[str]] = ...
    def __init__(
        self, name: str, unique_together: Collection[Sequence[str]] | None
    ) -> None: ...

class AlterIndexTogether(FieldRelatedOptionOperation):
    option_name: str = ...
    index_together: Collection[Sequence[str]] = ...
    def __init__(
        self, name: str, index_together: Collection[Sequence[str]] | None
    ) -> None: ...

class AlterOrderWithRespectTo(FieldRelatedOptionOperation):
    order_with_respect_to: str = ...
    def __init__(self, name: str, order_with_respect_to: str) -> None: ...

class AlterModelOptions(ModelOptionOperation):
    ALTER_OPTION_KEYS: Any = ...
    options: dict[str, str] = ...
    def __init__(self, name: str, options: dict[str, Any]) -> None: ...

class AlterModelManagers(ModelOptionOperation):
    managers: Any = ...
    def __init__(self, name: Any, managers: Any) -> None: ...

class IndexOperation(Operation):
    option_name: str = ...
    def model_name_lower(self) -> Any: ...

class AddIndex(IndexOperation):
    model_name: str = ...
    index: Index = ...
    def __init__(self, model_name: str, index: str | Index) -> None: ...

class RemoveIndex(IndexOperation):
    model_name: str = ...
    name: str = ...
    def __init__(self, model_name: str, name: str | Index) -> None: ...

class RenameIndex(IndexOperation):
    model_name: str
    new_name: str
    old_name: str | None
    old_fields: Sequence[str] | None
    def __init__(
        self,
        model_name: str,
        new_name: str,
        old_name: str | None = ...,
        old_fields: Sequence[str] | None = ...,
    ) -> None: ...
    @property
    def old_name_lower(self) -> str: ...
    @property
    def new_name_lower(self) -> str: ...

class AddConstraint(IndexOperation):
    def __init__(self, model_name: str, constraint: BaseConstraint) -> None: ...

class RemoveConstraint(IndexOperation):
    def __init__(self, model_name: str, name: str) -> None: ...
