from rest_framework import serializers
from .models import *
from .helper import *
from customers.serializers import CustomerSerializer
from ledgers.serializers import *
from questbanker_api.utils import get_current_user
import datetime
from django.utils import timezone


class OrganisationSuppliersSerializer(serializers.ModelSerializer):
    supplier_details = serializers.SerializerMethodField()

    customer = serializers.PrimaryKeyRelatedField(
        queryset=Customer.objects.all(),
        required=False,
        allow_null=True
    )

    class Meta:
        model = OrganisationSuppliers
        fields = '__all__'
        read_only_fields = ['added_by', 'organisation', 'date_added', 'last_updated_date']

    def create(self, validated_data):
        request = self.context.get('request')

        if request and hasattr(request, 'user'):
            validated_data['added_by'] = request.user

            # Dynamically get user's organisation
            organisation_id = get_current_user(request, 'organisation_id', None)
            if organisation_id:
                validated_data['organisation'] = Organisation.objects.get(id=organisation_id)

        supplier = OrganisationSuppliers.objects.create(**validated_data)
        return supplier

    def update(self, instance, validated_data):
        validated_data['last_updated_date'] = timezone.now()
        return super().update(instance, validated_data)

    def get_supplier_details(self, obj):
        if obj.customer:
            return CustomerSerializer(obj.customer).data
        return {
            "id": None,
            "name": obj.name or obj.bank_name or "External Supplier",
            "telephone": obj.telephone,
            "gender": obj.gender,
            "address": obj.address,
            "bank_name": obj.bank_name,
            "bank_acc_no": obj.bank_acc_no,
            "customer_type_name": "Non-member",
            "savings_accounts": [],
            "status": "external",
        }


class SupplierPaymentSerializer(serializers.ModelSerializer):
    class Meta:
        model = SupplierPayment
        fields = '__all__'
        read_only_fields = ('added_by', 'organisation')

    def validate_maturity_date(self, value):
        if isinstance(value, datetime.datetime):
            return value.date()
        return value

    def to_representation(self, instance):
        ret = super().to_representation(instance)

        if getattr(instance, 'transaction_date', None):
            ret['transaction_date'] = instance.transaction_date.isoformat()
        if getattr(instance, 'maturity_date', None):
            ret['maturity_date'] = instance.maturity_date.isoformat()

        return ret


class SupplierPayableSerializer(serializers.ModelSerializer):
    payments = SupplierPaymentSerializer(many=True, read_only=True)
    supplier_name = serializers.SerializerMethodField()

    class Meta:
        model = SupplierPayable
        fields = '__all__'
        read_only_fields = ('added_by', 'organisation')

    def get_supplier_name(self, obj):
        if getattr(obj.supplier, 'customer', None):
            return getattr(obj.supplier.customer, 'name', "N/A")
        return "N/A"

    def validate_maturity_date(self, value):
        if isinstance(value, datetime.datetime):
            return value.date()
        return value

    def to_representation(self, instance):
        ret = super().to_representation(instance)
        if getattr(instance, 'maturity_date', None):
            ret['maturity_date'] = instance.maturity_date.isoformat()
        if getattr(instance, 'transaction_date', None):
            ret['transaction_date'] = instance.transaction_date.isoformat()
        return ret


class ProductCategorySerializer(serializers.ModelSerializer):
    parent_name = serializers.CharField(read_only=True, source="parent.category_name")
    organisation = serializers.CharField(read_only=True)
    added_by = serializers.CharField(read_only=True)

    class Meta:
        model = ProductCategory
        fields = '__all__'


class ProductSerializer(serializers.ModelSerializer):
    stock_balance = serializers.SerializerMethodField()
    category_name = serializers.CharField(read_only=True, source="category.category_name")
    organisation = serializers.CharField(read_only=True)
    added_by = serializers.CharField(read_only=True)

    def get_stock_balance(self, obj):
        branch_id = self.context.get('branch_id')
        stock_total = get_stock_balance_by_product(obj.id, branch_id)
        return stock_total

    class Meta:
        model = Product
        fields = '__all__'


class StockSerializer(serializers.ModelSerializer):
    product_name = serializers.CharField(read_only=True, source="product.product_name")
    transaction = serializers.CharField(read_only=True, source="transaction.reference_no")
    stock_branch = serializers.CharField(read_only=True, source="stock_branch.name")
    added_by = serializers.CharField(read_only=True, source="added_by.username")

    class Meta:
        model = Stock
        fields = '__all__'


class OrganisationSeasonSerializer(serializers.ModelSerializer):
    organisation = serializers.CharField(read_only=True)
    added_by = serializers.CharField(read_only=True)

    class Meta:
        model = OrganisationSeason
        fields = '__all__'


class OrderSerializer(serializers.ModelSerializer):
    order_details = serializers.SerializerMethodField()
    teller = serializers.SerializerMethodField(read_only=True)
    customer = serializers.SerializerMethodField(read_only=True)
    debtor_account_name = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = Order
        fields = '__all__'

    def get_teller(self, transaction):
        if transaction.added_by:
            return transaction.added_by.username
        return ''

    def get_order_details(self, obj):
        if getattr(obj, 'transaction', None):
            transaction = obj.transaction
            return {
                "heading": getattr(transaction, 'heading', ''),
                "reference_no": getattr(transaction, 'reference_no', ''),
                "amount": getattr(transaction, 'amount', ''),
                "record_date": getattr(transaction, 'record_date', '')
            }
        return {"heading": "", "reference_no": "", "amount": "", "record_date": ""}

    def get_customer(self, obj):
        """
        Fetch customer name for all payment methods.
        First, try the related object.
        Then fallback to customer_id.
        Then fallback to NonCustomerOrders.
        """
        # 1. Try the related customer object
        customer_obj = getattr(obj, 'customer', None)
        if customer_obj:
            return {"name": getattr(customer_obj, 'name', 'N/A')}

        # 2. Fallback to customer_id
        customer_id = getattr(obj, 'customer_id', None)
        if customer_id:
            customer_obj = Customer.objects.filter(pk=customer_id).first()
            if customer_obj:
                return {"name": customer_obj.name}

        # 3. Fallback to NonCustomerOrders
        if getattr(obj, 'id', None):
            non_customer = NonCustomerOrders.objects.filter(order=obj.id).first()
            if non_customer:
                return {"name": getattr(non_customer, 'name', 'N/A')}

        # Default fallback
        return {"name": "N/A"}

    def get_debtor_account_name(self, obj):
        debtor = getattr(obj, 'debtor_account', None)
        if debtor:
            return getattr(debtor, 'account_name', None)
        return None



class CustomerRequestSerializer(serializers.ModelSerializer):
    customer_name = serializers.SerializerMethodField()
    customer_phone = serializers.CharField(source='customer.telephone', read_only=True)
    product_name = serializers.CharField(source='product.product_name', read_only=True)
    product_details = serializers.SerializerMethodField()
    
    class Meta:
        model = CustomerRequest
        fields = '__all__'
        read_only_fields = ('request_number', 'created_at')
    
    def get_customer_name(self, obj):
        return obj.customer.name if obj.customer else None
    
    def get_product_details(self, obj):
        return {
            'id': obj.product.id,
            'name': obj.product.product_name,
            'sale_price': obj.product.sale_price,
            'sale_unit_type': obj.product.sale_unit_type
        }


class AggregatedRequestItemSerializer(serializers.ModelSerializer):
    product_name = serializers.CharField(source='product.product_name', read_only=True)
    customer_name = serializers.CharField(source='customer.name', read_only=True)
    customer_phone = serializers.CharField(source='customer.telephone', read_only=True)
    cash_account_name = serializers.CharField(source='cash_account.account_name', read_only=True)

    class Meta:
        model = AggregatedRequestItem
        fields = ['id', 'customer', 'customer_name', 'customer_phone', 'product', 'product_name',
                  'quantity_requested', 'quantity_fulfilled', 'unit_price', 'total_cost', 'notes',
                  'payment_method', 'cash_account', 'cash_account_name', 'payment_transaction']


class AggregatedRequestSerializer(serializers.ModelSerializer):
    items = AggregatedRequestItemSerializer(many=True, required=False)
    created_by_name = serializers.CharField(source='created_by.username', read_only=True)
    service_provider_name = serializers.CharField(source='service_provider.name', read_only=True)
    requesting_organisation_name = serializers.CharField(source='organisation.name', read_only=True)
    
    class Meta:
        model = AggregatedRequest
        fields = '__all__'
        read_only_fields = ('request_number', 'created_by', 'organisation', 'status', 'created_at', 'updated_at')
    
    def create(self, validated_data):
        items_data = validated_data.pop('items', [])
        aggregated_request = AggregatedRequest.objects.create(**validated_data)
        
        for item_data in items_data:
            AggregatedRequestItem.objects.create(
                aggregated_request=aggregated_request,
                **item_data
            )
        
        return aggregated_request


class AggregatedStockSerializer(serializers.ModelSerializer):
    stock_details = serializers.SerializerMethodField()
    
    class Meta:
        model = AggregatedStock
        fields = '__all__'
    
    def get_stock_details(self, obj):
        return {
            'batch_number': obj.stock.batch_number,
            'product': obj.stock.product.product_name,
            'quantity': obj.stock.quantity
        }
