"""
Универсальные функции для управления фотографиями товаров, комплектов и категорий.
Устраняет дублирование кода для операций: delete, set_main, move_up, move_down.
"""
import json
from django.shortcuts import get_object_or_404, redirect
from django.contrib import messages
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from django.contrib.auth.decorators import login_required

from ..models import ProductPhoto, ProductKitPhoto, ProductCategoryPhoto


# ====================================
# Универсальные функции
# ====================================

def generic_photo_delete(request, pk, photo_model, redirect_url_name, parent_attr, permission):
    """
    Универсальное удаление фотографии.

    Args:
        request: HTTP request
        pk: ID фотографии
        photo_model: Модель фото (ProductPhoto, ProductKitPhoto, ProductCategoryPhoto)
        redirect_url_name: Имя URL для редиректа ('products:product-update', etc.)
        parent_attr: Имя атрибута родителя ('product', 'kit', 'category')
        permission: Требуемое разрешение ('products.change_product', etc.)
    """
    photo = get_object_or_404(photo_model, pk=pk)
    parent = getattr(photo, parent_attr)
    parent_id = parent.id

    # Проверка прав доступа
    if not request.user.has_perm(permission):
        messages.error(request, 'У вас нет прав для удаления фотографий.')
        return redirect(redirect_url_name, pk=parent_id)

    photo.delete()
    messages.success(request, 'Фото успешно удалено!')

    return redirect(redirect_url_name, pk=parent_id)


def generic_photo_set_main(request, pk, photo_model, redirect_url_name, parent_attr, permission):
    """
    Универсальная установка фото как главного (is_main=True).
    
    Автоматически сбрасывает is_main=False у старого главного фото.
    Constraint на уровне БД гарантирует, что у сущности может быть только одно is_main=True.

    Args:
        request: HTTP request
        pk: ID фотографии
        photo_model: Модель фото
        redirect_url_name: Имя URL для редиректа
        parent_attr: Имя атрибута родителя ('product', 'kit', 'category')
        permission: Требуемое разрешение
    """
    photo = get_object_or_404(photo_model, pk=pk)
    parent = getattr(photo, parent_attr)
    parent_id = parent.id

    # Проверка прав доступа
    if not request.user.has_perm(permission):
        messages.error(request, 'У вас нет прав для изменения порядка фотографий.')
        return redirect(redirect_url_name, pk=parent_id)

    # Если это уже главное фото, ничего не делаем
    if photo.is_main:
        messages.info(request, 'Это фото уже установлено как главное.')
        return redirect(redirect_url_name, pk=parent_id)

    # Сбрасываем is_main у старого главного фото
    filter_kwargs = {f"{parent_attr}_id": parent_id, 'is_main': True}
    old_main = photo_model.objects.filter(**filter_kwargs).first()
    if old_main:
        old_main.is_main = False
        old_main.save(update_fields=['is_main'])

    # Устанавливаем новое главное фото
    photo.is_main = True
    photo.save(update_fields=['is_main'])

    messages.success(request, 'Фото установлено как главное!')
    return redirect(redirect_url_name, pk=parent_id)


def generic_photo_move_up(request, pk, photo_model, redirect_url_name, parent_attr, permission):
    """
    Универсальное перемещение фото вверх (уменьшить order).

    Args:
        request: HTTP request
        pk: ID фотографии
        photo_model: Модель фото
        redirect_url_name: Имя URL для редиректа
        parent_attr: Имя атрибута родителя ('product', 'kit', 'category')
        permission: Требуемое разрешение
    """
    photo = get_object_or_404(photo_model, pk=pk)
    parent = getattr(photo, parent_attr)
    parent_id = parent.id

    # Проверка прав доступа
    if not request.user.has_perm(permission):
        messages.error(request, 'У вас нет прав для изменения порядка фотографий.')
        return redirect(redirect_url_name, pk=parent_id)

    # Если это уже первое фото
    if photo.order == 0:
        messages.info(request, 'Это фото уже первое в списке.')
        return redirect(redirect_url_name, pk=parent_id)

    # Находим предыдущее фото
    filter_kwargs = {
        f"{parent_attr}_id": parent_id,
        'order__lt': photo.order
    }
    prev_photo = photo_model.objects.filter(**filter_kwargs).order_by('-order').first()

    if prev_photo:
        # Меняем местами
        photo.order, prev_photo.order = prev_photo.order, photo.order
        photo.save()
        prev_photo.save()
        messages.success(request, 'Фото перемещено вверх!')

    return redirect(redirect_url_name, pk=parent_id)


def generic_photo_move_down(request, pk, photo_model, redirect_url_name, parent_attr, permission):
    """
    Универсальное перемещение фото вниз (увеличить order).

    Args:
        request: HTTP request
        pk: ID фотографии
        photo_model: Модель фото
        redirect_url_name: Имя URL для редиректа
        parent_attr: Имя атрибута родителя ('product', 'kit', 'category')
        permission: Требуемое разрешение
    """
    photo = get_object_or_404(photo_model, pk=pk)
    parent = getattr(photo, parent_attr)
    parent_id = parent.id

    # Проверка прав доступа
    if not request.user.has_perm(permission):
        messages.error(request, 'У вас нет прав для изменения порядка фотографий.')
        return redirect(redirect_url_name, pk=parent_id)

    # Находим следующее фото
    filter_kwargs = {
        f"{parent_attr}_id": parent_id,
        'order__gt': photo.order
    }
    next_photo = photo_model.objects.filter(**filter_kwargs).order_by('order').first()

    if next_photo:
        # Меняем местами
        photo.order, next_photo.order = next_photo.order, photo.order
        photo.save()
        next_photo.save()
        messages.success(request, 'Фото перемещено вниз!')
    else:
        messages.info(request, 'Это фото уже последнее в списке.')

    return redirect(redirect_url_name, pk=parent_id)


# ====================================
# Обертки для Product Photos
# ====================================

def product_photo_delete(request, pk):
    """Удаление фотографии товара"""
    return generic_photo_delete(
        request, pk,
        photo_model=ProductPhoto,
        redirect_url_name='products:product-update',
        parent_attr='product',
        permission='products.change_product'
    )


def product_photo_set_main(request, pk):
    """Установка фото товара как главного (order = 0)"""
    return generic_photo_set_main(
        request, pk,
        photo_model=ProductPhoto,
        redirect_url_name='products:product-update',
        parent_attr='product',
        permission='products.change_product'
    )


def product_photo_move_up(request, pk):
    """Переместить фото товара вверх (уменьшить order)"""
    return generic_photo_move_up(
        request, pk,
        photo_model=ProductPhoto,
        redirect_url_name='products:product-update',
        parent_attr='product',
        permission='products.change_product'
    )


def product_photo_move_down(request, pk):
    """Переместить фото товара вниз (увеличить order)"""
    return generic_photo_move_down(
        request, pk,
        photo_model=ProductPhoto,
        redirect_url_name='products:product-update',
        parent_attr='product',
        permission='products.change_product'
    )


# ====================================
# Обертки для ProductKit Photos
# ====================================

def productkit_photo_delete(request, pk):
    """Удаление фотографии комплекта"""
    return generic_photo_delete(
        request, pk,
        photo_model=ProductKitPhoto,
        redirect_url_name='products:productkit-update',
        parent_attr='kit',
        permission='products.change_productkit'
    )


def productkit_photo_set_main(request, pk):
    """Установка фото комплекта как главного (order = 0)"""
    return generic_photo_set_main(
        request, pk,
        photo_model=ProductKitPhoto,
        redirect_url_name='products:productkit-update',
        parent_attr='kit',
        permission='products.change_productkit'
    )


def productkit_photo_move_up(request, pk):
    """Переместить фото комплекта вверх (уменьшить order)"""
    return generic_photo_move_up(
        request, pk,
        photo_model=ProductKitPhoto,
        redirect_url_name='products:productkit-update',
        parent_attr='kit',
        permission='products.change_productkit'
    )


def productkit_photo_move_down(request, pk):
    """Переместить фото комплекта вниз (увеличить order)"""
    return generic_photo_move_down(
        request, pk,
        photo_model=ProductKitPhoto,
        redirect_url_name='products:productkit-update',
        parent_attr='kit',
        permission='products.change_productkit'
    )


# ====================================
# Обертки для Category Photos
# ====================================

def category_photo_delete(request, pk):
    """Удаление фотографии категории"""
    return generic_photo_delete(
        request, pk,
        photo_model=ProductCategoryPhoto,
        redirect_url_name='products:category-update',
        parent_attr='category',
        permission='products.change_productcategory'
    )


def category_photo_set_main(request, pk):
    """Установка фото категории как главного (order = 0)"""
    return generic_photo_set_main(
        request, pk,
        photo_model=ProductCategoryPhoto,
        redirect_url_name='products:category-update',
        parent_attr='category',
        permission='products.change_productcategory'
    )


def category_photo_move_up(request, pk):
    """Переместить фото категории вверх (уменьшить order)"""
    return generic_photo_move_up(
        request, pk,
        photo_model=ProductCategoryPhoto,
        redirect_url_name='products:category-update',
        parent_attr='category',
        permission='products.change_productcategory'
    )


def category_photo_move_down(request, pk):
    """Переместить фото категории вниз (увеличить order)"""
    return generic_photo_move_down(
        request, pk,
        photo_model=ProductCategoryPhoto,
        redirect_url_name='products:category-update',
        parent_attr='category',
        permission='products.change_productcategory'
    )


# ====================================
# AJAX Endpoints для массового удаления
# ====================================

@require_http_methods(["POST"])
@login_required
def product_photos_delete_bulk(request):
    """
    AJAX endpoint для массового удаления фотографий товара.

    Ожидает JSON: {photo_ids: [1, 2, 3]}
    Возвращает JSON: {success: true, deleted: 3} или {success: false, error: "..."}
    """
    # Проверка прав доступа
    if not request.user.has_perm('products.change_product'):
        return JsonResponse({
            'success': False,
            'error': 'У вас нет прав для удаления фотографий'
        }, status=403)

    try:
        # Получаем список photo_ids из JSON тела запроса
        data = json.loads(request.body)
        photo_ids = data.get('photo_ids', [])

        if not photo_ids or not isinstance(photo_ids, list):
            return JsonResponse({
                'success': False,
                'error': 'Неверный формат: требуется список photo_ids'
            }, status=400)

        # Удаляем фотографии
        deleted_count = 0
        for photo_id in photo_ids:
            try:
                photo = ProductPhoto.objects.get(pk=photo_id)
                photo.delete()  # Это вызовет ImageProcessor.delete_all_versions()
                deleted_count += 1
            except ProductPhoto.DoesNotExist:
                # Если фото не найдена, просто пропускаем
                continue
            except Exception as e:
                # Логируем ошибку но продолжаем удаление остальных
                import logging
                logger = logging.getLogger(__name__)
                logger.error(f"Error deleting photo {photo_id}: {str(e)}", exc_info=True)
                continue

        return JsonResponse({
            'success': True,
            'deleted': deleted_count
        })

    except json.JSONDecodeError:
        return JsonResponse({
            'success': False,
            'error': 'Неверный JSON формат'
        }, status=400)
    except Exception as e:
        import logging
        logger = logging.getLogger(__name__)
        logger.error(f"Bulk photo deletion error: {str(e)}", exc_info=True)
        return JsonResponse({
            'success': False,
            'error': f'Ошибка сервера: {str(e)}'
        }, status=500)


@require_http_methods(["POST"])
@login_required
def productkit_photos_delete_bulk(request):
    """
    AJAX endpoint для массового удаления фотографий комплекта.

    Ожидает JSON: {photo_ids: [1, 2, 3]}
    Возвращает JSON: {success: true, deleted: 3} или {success: false, error: "..."}
    """
    # Проверка прав доступа
    if not request.user.has_perm('products.change_productkit'):
        return JsonResponse({
            'success': False,
            'error': 'У вас нет прав для удаления фотографий'
        }, status=403)

    try:
        # Получаем список photo_ids из JSON тела запроса
        data = json.loads(request.body)
        photo_ids = data.get('photo_ids', [])

        if not photo_ids or not isinstance(photo_ids, list):
            return JsonResponse({
                'success': False,
                'error': 'Неверный формат: требуется список photo_ids'
            }, status=400)

        # Удаляем фотографии
        deleted_count = 0
        for photo_id in photo_ids:
            try:
                photo = ProductKitPhoto.objects.get(pk=photo_id)
                photo.delete()  # Это вызовет ImageProcessor.delete_all_versions()
                deleted_count += 1
            except ProductKitPhoto.DoesNotExist:
                # Если фото не найдена, просто пропускаем
                continue
            except Exception as e:
                # Логируем ошибку но продолжаем удаление остальных
                import logging
                logger = logging.getLogger(__name__)
                logger.error(f"Error deleting kit photo {photo_id}: {str(e)}", exc_info=True)
                continue

        return JsonResponse({
            'success': True,
            'deleted': deleted_count
        })

    except json.JSONDecodeError:
        return JsonResponse({
            'success': False,
            'error': 'Неверный JSON формат'
        }, status=400)
    except Exception as e:
        import logging
        logger = logging.getLogger(__name__)
        logger.error(f"Bulk kit photo deletion error: {str(e)}", exc_info=True)
        return JsonResponse({
            'success': False,
            'error': f'Ошибка сервера: {str(e)}'
        }, status=500)
