from rest_framework import serializers
from .models import Cuenta, Asiento, DetalleAsiento, DatosEmpresa, AuditoriaLog

class DatosEmpresaSerializer(serializers.ModelSerializer):
    class Meta:
        model = DatosEmpresa
        fields = '__all__'

class AuditoriaLogSerializer(serializers.ModelSerializer):
    usuario = serializers.ReadOnlyField(source='usuario.username')
    rol = serializers.SerializerMethodField()

    class Meta:
        model = AuditoriaLog
        fields = ['id', 'usuario', 'rol', 'accion', 'fecha_hora']

    def get_rol(self, obj):
        if not obj.usuario: return 'DESCONOCIDO'
        if obj.usuario.is_superuser: return 'ADMINISTRADOR'
        if hasattr(obj.usuario, 'perfil'): return obj.usuario.perfil.rol
        return 'AUXILIAR'
from django.contrib.auth.models import User
from decimal import Decimal

class CuentaSerializer(serializers.ModelSerializer):
    tiene_movimientos = serializers.SerializerMethodField()

    class Meta:
        model = Cuenta
        fields = ['codigo', 'nombre', 'movimiento', 'tipo_saldo', 'activa', 'tiene_movimientos']

    def get_tiene_movimientos(self, obj):
        from .models import DetalleAsiento as RenglonAsiento
        return RenglonAsiento.objects.filter(cuenta_id=obj.id).exists()

class DetalleAsientoSerializer(serializers.ModelSerializer):
    cuenta_nombre = serializers.ReadOnlyField(source='cuenta.nombre')
    cuenta_codigo = serializers.ReadOnlyField(source='cuenta.codigo')

    class Meta:
        model = DetalleAsiento
        fields = ['id', 'cuenta', 'cuenta_codigo', 'cuenta_nombre', 'descripcion', 'debe', 'haber']

class AsientoSerializer(serializers.ModelSerializer):
    detalles = DetalleAsientoSerializer(many=True)
    creado_por = serializers.ReadOnlyField(source='creado_por.username')
    
    total_debe = serializers.SerializerMethodField()
    total_haber = serializers.SerializerMethodField()

    class Meta:
        model = Asiento
        fields = ['id', 'fecha', 'glosa', 'creado_por', 'detalles', 'total_debe', 'total_haber']

    def get_total_debe(self, obj):
        return sum(d.debe for d in obj.detalles.all())
        
    def get_total_haber(self, obj):
        return sum(d.haber for d in obj.detalles.all())

    def to_representation(self, instance):
        ret = super().to_representation(instance)
        tipo = self.context.get('tipo', 'general')
        if tipo == 'resumido':
            from django.db.models import Sum
            from django.db.models.functions import Coalesce
            from django.db.models import DecimalField, Value
            grouped = instance.detalles.values(
                'cuenta_id', 'cuenta__codigo', 'cuenta__nombre'
            ).annotate(
                total_debe=Coalesce(Sum('debe'), Value(0.00), output_field=DecimalField()),
                total_haber=Coalesce(Sum('haber'), Value(0.00), output_field=DecimalField())
            ).order_by('cuenta__codigo')
            
            ret['detalles'] = [
                {
                    'id': None,
                    'cuenta': g['cuenta_id'],
                    'cuenta_codigo': g['cuenta__codigo'],
                    'cuenta_nombre': g['cuenta__nombre'],
                    'descripcion': 'Movimiento Consolidado',
                    'debe': float(g['total_debe']),
                    'haber': float(g['total_haber'])
                }
                for g in grouped
            ]
        return ret

    def validate(self, data):
        from django.utils import timezone
        fecha = data.get('fecha')
        if fecha and fecha > timezone.localdate():
            raise serializers.ValidationError({'fecha': 'No se pueden registrar asientos contables con fechas futuras.'})

        detalles = data.get('detalles', [])
        total_debe = Decimal('0.00')
        total_haber = Decimal('0.00')

        for detalle in detalles:
            cuenta = detalle.get('cuenta')
            if cuenta.movimiento != 'SI':
                raise serializers.ValidationError(f"La cuenta {cuenta.codigo} no acepta movimientos (es cuenta madre/agrupación).")
            
            debe = detalle.get('debe', Decimal('0.00'))
            haber = detalle.get('haber', Decimal('0.00'))
            total_debe += debe
            total_haber += haber

        if total_debe != total_haber:
            raise serializers.ValidationError({'error': 'Error de partida doble: El total del Debe y del Haber deben coincidir.'})

        return data

    def create(self, validated_data):
        from django.db import transaction
        detalles_data = validated_data.pop('detalles')
        
        # Default user until auth is fully implemented
        user, _ = User.objects.get_or_create(username='admin', defaults={'email': 'admin@example.com'})
        validated_data['creado_por'] = user

        with transaction.atomic():
            asiento = Asiento.objects.create(**validated_data)
            for detalle_data in detalles_data:
                DetalleAsiento.objects.create(asiento=asiento, **detalle_data)
        
        return asiento

    def update(self, instance, validated_data):
        from django.db import transaction
        detalles_data = validated_data.pop('detalles', None)
        
        instance.fecha = validated_data.get('fecha', instance.fecha)
        instance.glosa = validated_data.get('glosa', instance.glosa)
        
        with transaction.atomic():
            instance.save()
            
            if detalles_data is not None:
                # Borrar detalles viejos
                instance.detalles.all().delete()
                # Insertar los nuevos actualizados
                for detalle_data in detalles_data:
                    DetalleAsiento.objects.create(asiento=instance, **detalle_data)
                    
        return instance
