# Copyright (c) 2023-present Pi Dash Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.

"""
Database router for read replica selection.
This router determines which database to use for read/write operations
based on the request context set by the ReadReplicaRoutingMiddleware.
"""

import logging
from typing import Type

from django.db import models

from .request_scope import should_use_read_replica

logger = logging.getLogger("pi_dash.db")


class ReadReplicaRouter:
    """
    Database router that directs read operations to replica when appropriate.
    This router works in conjunction with ReadReplicaRoutingMiddleware to:
    - Route read operations to replica database when request context allows
    - Always route write operations to primary database
    - Ensure migrations only run on primary database
    """

    def db_for_read(self, model: Type[models.Model], **hints) -> str:
        """
        Determine which database to use for read operations.
        Args:
            model: The Django model class being queried
            **hints: Additional routing hints
        Returns:
            str: Database alias ('replica' or 'default')
        """
        if should_use_read_replica():
            logger.debug(f"Routing read for {model._meta.label} to replica database")
            return "replica"
        else:
            logger.debug(f"Routing read for {model._meta.label} to primary database")
            return "default"

    def db_for_write(self, model: Type[models.Model], **hints) -> str:
        """
        Determine which database to use for write operations.
        All write operations always go to the primary database to ensure
        data consistency and avoid replication lag issues.
        Args:
            model: The Django model class being written to
            **hints: Additional routing hints
        Returns:
            str: Always returns 'default' (primary database)
        """
        logger.debug(f"Routing write for {model._meta.label} to primary database")
        return "default"

    def allow_migrate(self, db: str, app_label: str, model_name: str = None, **hints) -> bool:
        """
        Ensure migrations only run on the primary database.
        Args:
            db: Database alias
            app_label: Application label
            model_name: Model name (optional)
            **hints: Additional routing hints
        Returns:
            bool: True if migration is allowed on this database
        """
        # Only allow migrations on the primary database
        allowed = db == "default"
        if not allowed:
            logger.debug(f"Blocking migration for {app_label} on {db} database")
        return allowed
