# -*- coding: utf-8 -*-
"""
Сервис онбординга новых тенантов.

Единственный источник истины для создания тенанта и всех связанных сущностей.
"""
import logging
from django.db import connection, transaction
from django.utils import timezone
from django.conf import settings
from django.core.management import call_command

from tenants.models import Client, Domain, TenantRegistration, Subscription

logger = logging.getLogger(__name__)


class TenantOnboardingService:
    """
    Сервис онбординга нового тенанта.

    Отвечает за полный цикл создания тенанта:
    - Создание Client (тенант)
    - Создание Domain (домен)
    - Создание Subscription (подписка)
    - Миграции схемы
    - Создание владельца (owner)
    - Инициализация системных данных
    """

    @classmethod
    @transaction.atomic
    def activate_registration(cls, registration: TenantRegistration, admin_user=None) -> Client:
        """
        Полная активация заявки на регистрацию тенанта.

        Args:
            registration: Заявка на регистрацию
            admin_user: Администратор, одобривший заявку (опционально)

        Returns:
            Client: Созданный тенант

        Raises:
            ValueError: Если тенант уже существует
        """
        logger.info(f"Начало активации заявки: {registration.schema_name}")

        # 1. Проверка уникальности
        if Client.objects.filter(schema_name=registration.schema_name).exists():
            raise ValueError(f"Тенант с schema_name '{registration.schema_name}' уже существует!")

        # 2. Создание тенанта
        client = cls._create_client(registration)

        # 3. Создание домена
        domain = cls._create_domain(client, registration)

        # 4. Применение миграций
        cls._run_migrations(client)

        # 5. Создание подписки
        subscription = cls._create_subscription(client)

        # 6. Инициализация данных тенанта (в контексте tenant schema)
        # CustomUser теперь в TENANT_APPS - создаётся в схеме тенанта
        connection.set_tenant(client)
        try:
            cls._init_tenant_users(registration)
            cls._init_tenant_data()
        finally:
            connection.set_schema_to_public()

        # 8. Отправка email владельцу
        cls._send_welcome_email(registration)

        # 8. Обновление статуса заявки
        cls._finalize_registration(registration, client, admin_user)

        logger.info(f"Заявка {registration.id} успешно активирована. Тенант: {client.id}")
        return client

    @classmethod
    def init_tenant_data(cls, reset: bool = False):
        """
        Инициализация системных данных тенанта.

        Вызывается в контексте схемы тенанта (connection.set_tenant уже выполнен).

        Args:
            reset: Если True, удаляет и пересоздаёт данные
        """
        from customers.models import Customer
        from orders.services import OrderStatusService, PaymentMethodService
        from inventory.services import WarehouseService, ShowcaseService
        from products.services import UnitOfMeasureService

        # 1. Системный клиент
        logger.info("Создание системного клиента...")
        if reset:
            Customer.objects.filter(is_system_customer=True).delete()
        customer, created = Customer.get_or_create_system_customer()
        logger.info(f"Системный клиент: {'создан' if created else 'уже существует'}")

        # 2. Статусы заказов
        logger.info("Создание статусов заказов...")
        if reset:
            from orders.models import OrderStatus
            OrderStatus.objects.filter(is_system=True).delete()
        OrderStatusService.create_default_statuses()
        logger.info("Статусы заказов созданы")

        # 3. Способы оплаты
        logger.info("Создание способов оплаты...")
        if reset:
            PaymentMethodService.reset_default_methods()
        else:
            PaymentMethodService.create_default_methods()
        logger.info("Способы оплаты созданы")

        # 4. Склад по умолчанию
        logger.info("Создание склада по умолчанию...")
        if reset:
            warehouse = WarehouseService.reset_default()
        else:
            warehouse, created = WarehouseService.get_or_create_default()
        logger.info(f"Склад по умолчанию: {warehouse.name}")

        # 5. Витрина по умолчанию
        logger.info("Создание витрины по умолчанию...")
        if reset:
            showcase = ShowcaseService.reset_default(warehouse)
        else:
            showcase, created = ShowcaseService.get_or_create_default(warehouse)
        logger.info(f"Витрина по умолчанию: {showcase.name}")

        # 6. Единицы измерения
        logger.info("Создание единиц измерения...")
        if reset:
            UnitOfMeasureService.reset_default_units()
        else:
            UnitOfMeasureService.create_default_units()
        logger.info("Единицы измерения созданы")

    # ==================== Приватные методы ====================

    @classmethod
    def _create_client(cls, registration: TenantRegistration) -> Client:
        """Создание тенанта (Client)."""
        logger.info(f"Создание тенанта: {registration.schema_name}")
        client = Client.objects.create(
            schema_name=registration.schema_name,
            name=registration.shop_name,
            owner_email=registration.owner_email,
            owner_name=registration.owner_name,
            phone=registration.phone,
            is_active=True
        )
        logger.info(f"Тенант создан: {client.id}")
        return client

    @classmethod
    def _create_domain(cls, client: Client, registration: TenantRegistration) -> Domain:
        """Создание домена для тенанта."""
        domain_base = settings.TENANT_DOMAIN_BASE
        # Убираем порт из домена (django-tenants ищет по hostname без порта)
        if ':' in domain_base:
            domain_base = domain_base.split(':')[0]

        domain_name = f"{registration.schema_name}.{domain_base}"
        logger.info(f"Создание домена: {domain_name}")

        domain = Domain.objects.create(
            domain=domain_name,
            tenant=client,
            is_primary=True
        )
        logger.info(f"Домен создан: {domain.id}")
        return domain

    @classmethod
    def _run_migrations(cls, client: Client):
        """Применение миграций для схемы тенанта."""
        logger.info(f"Применение миграций для тенанта: {client.schema_name}")
        try:
            call_command('migrate_schemas', schema_name=client.schema_name, verbosity=1)
            logger.info("Миграции успешно применены")
        except Exception as e:
            logger.error(f"Ошибка при применении миграций: {e}", exc_info=True)
            raise

    @classmethod
    def _create_subscription(cls, client: Client) -> Subscription:
        """Создание триальной подписки."""
        logger.info(f"Создание триальной подписки для тенанта: {client.id}")
        subscription = Subscription.create_trial(client)
        logger.info(f"Подписка создана: {subscription.id}, истекает: {subscription.expires_at}")
        return subscription

    @classmethod
    def _init_tenant_users(cls, registration: TenantRegistration):
        """
        Создание пользователей тенанта: владелец + техподдержка платформы.

        ВАЖНО: CustomUser в TENANT_APPS - создаётся в схеме тенанта.
        Вызывается в контексте tenant schema (connection.set_tenant уже выполнен).

        Django Admin доступна только для PlatformAdmin (из public schema).
        CustomUser используют только фронтенд.
        """
        from accounts.models import CustomUser

        # 1. Владелец тенанта
        if not CustomUser.objects.filter(email=registration.owner_email).exists():
            owner = CustomUser.objects.create_user(
                email=registration.owner_email,
                name=registration.owner_name,
                password=None,  # Пароль будет установлен через ссылку
            )
            owner.is_email_confirmed = True
            owner.email_confirmed_at = timezone.now()
            owner.is_active = False  # Неактивен до установки пароля
            owner.save()
            logger.info(f"Аккаунт владельца создан: {owner.id}")

            # Назначаем роль owner
            cls._assign_owner_role(owner)
        else:
            logger.warning(f"Пользователь {registration.owner_email} уже существует")

        # 2. Техподдержка платформы
        # SECURITY: НЕ создаём отдельную учетку CustomUser для саппорта
        # PlatformAdmin с is_superuser=True уже имеет полный доступ к tenant
        # через PlatformAdminBackend (может залогиниться и зайти в /admin/)
        logger.info("Техподдержка: используется PlatformAdmin (отдельный CustomUser НЕ создаётся)")

    @classmethod
    def _assign_owner_role(cls, owner):
        """Назначение роли owner владельцу тенанта."""
        try:
            from user_roles.services import RoleService
            from user_roles.models import Role

            RoleService.create_default_roles()
            RoleService.assign_role_to_user(owner, Role.OWNER, created_by=None)
            logger.info(f"Роль owner назначена: {owner.email}")
        except Exception as e:
            logger.error(f"Ошибка при назначении роли: {e}", exc_info=True)


    @classmethod
    def _init_tenant_data(cls):
        """Инициализация системных данных тенанта."""
        try:
            cls.init_tenant_data(reset=False)
        except Exception as e:
            logger.error(f"Ошибка при инициализации данных: {e}", exc_info=True)
            # Не прерываем процесс

    @classmethod
    def _send_welcome_email(cls, registration: TenantRegistration):
        """Отправка приветственного письма владельцу."""
        try:
            from tenants.services.email import send_password_setup_email
            send_password_setup_email(registration)
            logger.info(f"Письмо отправлено: {registration.owner_email}")
        except Exception as e:
            logger.error(f"Ошибка при отправке письма: {e}", exc_info=True)
            # Не прерываем процесс

    @classmethod
    def _finalize_registration(cls, registration: TenantRegistration, client: Client, admin_user):
        """Финализация заявки на регистрацию."""
        registration.status = TenantRegistration.STATUS_APPROVED
        registration.processed_at = timezone.now()

        # admin_user теперь должен быть PlatformAdmin
        if admin_user is not None:
            from platform_admin.models import PlatformAdmin
            if isinstance(admin_user, PlatformAdmin):
                registration.processed_by = admin_user
            else:
                logger.warning(f"admin_user не является PlatformAdmin: {type(admin_user)}")
                registration.processed_by = None
        else:
            registration.processed_by = None

        registration.tenant = client
        registration.save()
        logger.info(f"Заявка {registration.id} финализирована")
