"""
Module Settings — Views (API Layer)

ویوهای REST API سیستم تنظیمات ماژولار.
"""
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ViewSet

from .exceptions import (
    InvalidSettingsPath,
    ModuleSchemaNotRegistered,
    SettingsNotFoundException,
    SettingsValidationError,
)
from .serializers import (
    ModuleInfoSerializer,
    ModuleSettingsUpdateSerializer,
    SettingSectionUpdateSerializer,
    SettingValueUpdateSerializer,
)
from .services import ModuleSettingsService


class ModuleSettingsViewSet(ViewSet):
    """
    ViewSet برای مدیریت تنظیمات ماژول‌ها.

    Endpoints:
    - GET    /api/v1/settings/modules/              → لیست ماژول‌های دارای تنظیمات
    - GET    /api/v1/settings/modules/{module_key}/  → دریافت تنظیمات ماژول
    - PUT    /api/v1/settings/modules/{module_key}/  → بروزرسانی تنظیمات کامل
    - GET    /api/v1/settings/modules/{module_key}/schema/  → دریافت schema
    - POST   /api/v1/settings/modules/{module_key}/set-value/  → تغییر یک تنظیم
    - POST   /api/v1/settings/modules/{module_key}/set-section/  → تغییر یک بخش
    - POST   /api/v1/settings/modules/{module_key}/reset/  → بازنشانی به پیش‌فرض
    """

    permission_classes = [IsAuthenticated]
    lookup_field = "module_key"

    def list(self, request):
        """لیست ماژول‌های دارای تنظیمات."""
        tenant_id = getattr(request.tenant, "id", None) if hasattr(request, "tenant") else None
        modules = ModuleSettingsService.list_available_modules(tenant_id=tenant_id)
        serializer = ModuleInfoSerializer(modules, many=True)
        return Response({"data": serializer.data})

    def retrieve(self, request, module_key=None):
        """دریافت تنظیمات یک ماژول."""
        if not hasattr(request, "tenant") or not request.tenant:
            return Response(
                {"error": {"code": "NO_TENANT", "message": "Tenant not found"}},
                status=status.HTTP_400_BAD_REQUEST,
            )

        try:
            data = ModuleSettingsService.get(
                module_key=module_key,
                tenant_id=request.tenant.id,
            )
            return Response(
                {
                    "data": {
                        "module_key": module_key,
                        "settings_data": data,
                    }
                }
            )
        except ModuleSchemaNotRegistered as e:
            return Response(
                e.to_dict(),
                status=status.HTTP_404_NOT_FOUND,
            )

    def update(self, request, module_key=None):
        """بروزرسانی تنظیمات کامل ماژول."""
        if not hasattr(request, "tenant") or not request.tenant:
            return Response(
                {"error": {"code": "NO_TENANT", "message": "Tenant not found"}},
                status=status.HTTP_400_BAD_REQUEST,
            )

        serializer = ModuleSettingsUpdateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        try:
            data = ModuleSettingsService.save_settings(
                module_key=module_key,
                tenant_id=request.tenant.id,
                settings_data=serializer.validated_data["settings_data"],
                user_id=request.user.id if request.user.is_authenticated else None,
            )
            return Response(
                {
                    "data": {
                        "module_key": module_key,
                        "settings_data": data,
                    }
                }
            )
        except SettingsValidationError as e:
            return Response(e.to_dict(), status=status.HTTP_400_BAD_REQUEST)
        except ModuleSchemaNotRegistered as e:
            return Response(e.to_dict(), status=status.HTTP_404_NOT_FOUND)

    @action(detail=True, methods=["get"], url_path="schema")
    def schema(self, request, module_key=None):
        """دریافت schema تنظیمات ماژول."""
        try:
            schema = ModuleSettingsService.get_schema(module_key)
            return Response({"data": schema})
        except ModuleSchemaNotRegistered as e:
            return Response(e.to_dict(), status=status.HTTP_404_NOT_FOUND)

    @action(detail=True, methods=["post"], url_path="set-value")
    def set_value(self, request, module_key=None):
        """تغییر مقدار یک تنظیم خاص."""
        if not hasattr(request, "tenant") or not request.tenant:
            return Response(
                {"error": {"code": "NO_TENANT", "message": "Tenant not found"}},
                status=status.HTTP_400_BAD_REQUEST,
            )

        serializer = SettingValueUpdateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        try:
            data = ModuleSettingsService.set_value(
                module_key=module_key,
                tenant_id=request.tenant.id,
                path=serializer.validated_data["path"],
                value=serializer.validated_data["value"],
                user_id=request.user.id if request.user.is_authenticated else None,
            )
            return Response(
                {
                    "data": {
                        "module_key": module_key,
                        "settings_data": data,
                    }
                }
            )
        except InvalidSettingsPath as e:
            return Response(e.to_dict(), status=status.HTTP_400_BAD_REQUEST)
        except SettingsValidationError as e:
            return Response(e.to_dict(), status=status.HTTP_400_BAD_REQUEST)

    @action(detail=True, methods=["post"], url_path="set-section")
    def set_section(self, request, module_key=None):
        """تغییر تنظیمات یک بخش."""
        if not hasattr(request, "tenant") or not request.tenant:
            return Response(
                {"error": {"code": "NO_TENANT", "message": "Tenant not found"}},
                status=status.HTTP_400_BAD_REQUEST,
            )

        serializer = SettingSectionUpdateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        try:
            data = ModuleSettingsService.save_section(
                module_key=module_key,
                tenant_id=request.tenant.id,
                section_key=serializer.validated_data["section_key"],
                section_data=serializer.validated_data["section_data"],
                user_id=request.user.id if request.user.is_authenticated else None,
            )
            return Response(
                {
                    "data": {
                        "module_key": module_key,
                        "settings_data": data,
                    }
                }
            )
        except SettingsValidationError as e:
            return Response(e.to_dict(), status=status.HTTP_400_BAD_REQUEST)

    @action(detail=True, methods=["post"], url_path="reset")
    def reset(self, request, module_key=None):
        """بازنشانی تنظیمات به مقادیر پیش‌فرض."""
        if not hasattr(request, "tenant") or not request.tenant:
            return Response(
                {"error": {"code": "NO_TENANT", "message": "Tenant not found"}},
                status=status.HTTP_400_BAD_REQUEST,
            )

        try:
            data = ModuleSettingsService.reset_to_defaults(
                module_key=module_key,
                tenant_id=request.tenant.id,
                user_id=request.user.id if request.user.is_authenticated else None,
            )
            return Response(
                {
                    "data": {
                        "module_key": module_key,
                        "settings_data": data,
                    }
                }
            )
        except ModuleSchemaNotRegistered as e:
            return Response(e.to_dict(), status=status.HTTP_404_NOT_FOUND)
