from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.views import APIView
from django.db.models import Q
from .serializers import *
from .models import *
from .exservices_helper import *
from organisations.models import OrganisationSetting
from questbanker_api.utils import get_current_user
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.response import Response
from rest_framework import status
from django.http import Http404
import threading
from datetime import datetime
from ledgers.ledgers_helper import generate_reference_no,get_chart_of_account_by_code
from ledgers.models import SystemTransactions,OrganisationSubAccount,CashAccounts,BankAccounts
from customers.models import Customer, GroupMembership

class SMSTypesView(viewsets.ModelViewSet):
    serializer_class = SMSTypesSerializer

    def get_queryset(self):
        return SMSTypes.objects.all().order_by('-id')

class OrganisationFreeSmsAwardView(viewsets.ModelViewSet):
    serializer_class = OrganisationFreeSmsAwardSerializer
    def get_queryset(self):
        organisation = self.request.GET.get('organisation', None)
        start        = self.request.GET.get('s', None)
        end          = self.request.GET.get('e', None)
        query_filter = {}
        if organisation:
            query_filter['organisation__id'] = organisation 
        if start:
            query_filter['date_added__date__gte'] = start 
        if end:
            query_filter['date_added__date__lte'] = end 
        return OrganisationFreeSmsAward.objects.filter(**query_filter).order_by('-id')
    
    def perform_create(self, serializer):
        serializer.save(updated_by=self.request.user,added_by=self.request.user)


class SMSRequestViewset(viewsets.ModelViewSet):
    serializer_class = SMSRequestSerializer
    def get_queryset(self):
        process_type = self.request.GET.get('process_type', None)
        status       = self.request.GET.get('status', None)
        start        = self.request.GET.get('s', None)
        end          = self.request.GET.get('e', None)
        query_filter = {}
        if start:
            query_filter['date_added__date__gte'] = start 
        if end:
            query_filter['date_added__date__lte'] = end 
        if status:
            query_filter['status'] = status
        if process_type == 'fetch-single':
            organisation_id = get_current_user(self.request, 'organisation_id', None)
            query_filter['organisation__id'] = organisation_id
        return SMSRequest.objects.filter(**query_filter).order_by('-id')
    
    def perform_create(self, serializer):
        organisation_id = get_current_user(self.request, 'organisation_id', None)
        serializer.save(organisation_id=organisation_id,requested_by=self.request.user)

    def perform_update(self,serializer):
        updated_instance = serializer.save(approved_by=self.request.user)

        if updated_instance and updated_instance.status == 'approved':
            #sms purchase chart of account
            debit_chart_code = "sys-536"
            debit_chart_chart = OrganisationSubAccount.objects.filter(account_code=debit_chart_code, account_organisation=updated_instance.organisation).first()
            # Generate reference number
            reference_no = generate_reference_no(debit_chart_chart.account_line, updated_instance.organisation.id)
            
            heading = 'SMS Purchase by '+ updated_instance.organisation.name+' ('+ updated_instance.organisation.registration_no +')'
            saved_transaction = SystemTransactions.objects.create(
                amount=updated_instance.approved_amount,
                heading=heading, 
                reference_no=reference_no,
                payment_method=updated_instance.payment_method, 
                voucher_no='',
                debit_chart=debit_chart_chart,
                credit_chart=updated_instance.selected_account,
                branch=updated_instance.requested_by.user_organisation_branch, 
                added_by=updated_instance.requested_by)

            if saved_transaction:
                SmsPurchaseTransactions.objects.create(request=updated_instance,transaction=saved_transaction)
                #Register income for QDF from the sale of SMS
                current = User.objects.get(pk=self.request.user.id)
                if current:
                    debit_chart = None
                    base_sms_cost_client = 0
                    base_sms_cost_qdf    = 0

                    base_sms_cost_client_obj = OrganisationSetting.objects.filter(org_setting__id=updated_instance.requested_by.user_organisation_branch.branch_organisation.id,setting_key='unit_sms_cost').first()
                    if base_sms_cost_client_obj:
                        base_sms_cost_client = float(base_sms_cost_client_obj.setting_value)

                    base_sms_cost_obj = OrganisationSetting.objects.filter(org_setting__id=current.user_organisation_branch.branch_organisation.id,setting_key='unit_sms_cost').first()
                    if base_sms_cost_obj:
                        base_sms_cost_qdf = float(base_sms_cost_obj.setting_value)

                    # Check if cash account.
                    if updated_instance.payment_method == 'cash':
                        account = CashAccounts.objects.filter(chart__account_organisation__id=current.user_organisation_branch.branch_organisation.id).first()
                        if account:
                            debit_chart = account.chart
                    # Check if bank account.
                    if updated_instance.payment_method == 'bank':
                        account = BankAccounts.objects.filter(chart__account_organisation__id=current.user_organisation_branch.branch_organisation.id).first()
                        if account:
                            debit_chart = account.chart
                    
                    if debit_chart:
                        credit_income_from_sms_chart = get_chart_of_account_by_code('sys-4221',current.user_organisation_branch.branch_organisation.id)
                        reference_no = generate_reference_no(credit_income_from_sms_chart.account_line,current.user_organisation_branch.branch_organisation.id)
                        heading      = 'SMS Charge: Income from sms top-up for ' + updated_instance.requested_by.user_organisation_branch.branch_organisation.name
                        if base_sms_cost_client > 0:
                            total_sms_bought = (updated_instance.approved_amount / base_sms_cost_client)
                            profit_per_sms   = base_sms_cost_client - base_sms_cost_qdf
                            if profit_per_sms < 0:
                                profit_per_sms = 0
                            total_income = total_sms_bought * profit_per_sms
                            sms_charge_fields = {
                                "heading":heading,"coment":heading,
                                "amount":total_income,
                                "credit_chart":credit_income_from_sms_chart,
                                "debit_chart":debit_chart,
                                "reference_no":reference_no,
                                "payment_method":updated_instance.payment_method,
                                "record_date":datetime.now(),
                                "added_by":current,
                                "branch":current.user_organisation_branch
                            }
                            SystemTransactions.objects.create(**sms_charge_fields)
                
class SMSGeneralSettingsView(APIView):
        def get(self, request, format=None):
            settings = {}
            sms_settings_keys = [
                'is_sms_on','is_manual_selection_on','preselect_manual_sms','is_new_user_notification',
                'is_sms_errors_on','is_password_reset_sms_on',"award_free_sms",
                'free_sms_frequency','free_sms_to_subscribers','loan_payment_reminder'
            ]

            organisation_id = get_current_user(self.request, 'organisation_id', None)
            for sms_settings_key in sms_settings_keys:
                sms_setting   = OrganisationSetting.objects.filter(org_setting__id=organisation_id,setting_key=sms_settings_key).first()
                if sms_setting:
                    settings[sms_settings_key] = sms_setting.setting_value
                else:
                    settings[sms_settings_key] = 'off'
                    if sms_settings_key == 'free_sms_frequency':
                        settings[sms_settings_key] = 'monthly'
                    if sms_settings_key == 'free_sms_to_subscribers':
                        settings[sms_settings_key] = 0
            self.update_organisation_subScription(organisation_id)
            return Response(settings)
        
        def update_organisation_subScription(self,organisation_id):
            sms_type_ids = OrganisationSmsSubscription.objects.all().values_list('sms_type__id', flat=True)
            unassigned_types = SMSTypes.objects.all().exclude(id__in=sms_type_ids)
            if unassigned_types:
                for unassigned_type in unassigned_types:
                    data = {"sms_type":unassigned_type,"organisation":Organisation.objects.get(pk=organisation_id), "charge":unassigned_type.base_fee,"added_by":self.request.user, "last_updated_by":self.request.user,"is_subscribed":True}
                    OrganisationSmsSubscription.objects.create(**data)
            
        def post(self, request, format=None):
            organisation_id = get_current_user(self.request, 'organisation_id', None)
            settings_data   = [
                {"setting_key":"is_sms_on","setting_value":request.data.get('is_sms_on')},
                {"setting_key":"award_free_sms","setting_value":request.data.get('award_free_sms')},
                {"setting_key":"is_manual_selection_on","setting_value":request.data.get('is_manual_selection_on')},
                {"setting_key":"preselect_manual_sms","setting_value":request.data.get('preselect_manual_sms')},
                {"setting_key":"is_password_reset_sms_on","setting_value":request.data.get('is_password_reset_sms_on')},
                {"setting_key":"is_sms_errors_on","setting_value":request.data.get('is_sms_errors_on')},
                {"setting_key":"free_sms_to_subscribers","setting_value":request.data.get('free_sms_to_subscribers')},
                {"setting_key":"free_sms_frequency","setting_value":request.data.get('free_sms_frequency')},
                {"setting_key":"loan_payment_reminder","setting_value":request.data.get('loan_payment_reminder')},
                {"setting_key":"is_new_user_notification","setting_value":request.data.get('is_new_user_notification')}
            ]
            for data in settings_data:
                sms_setting   = OrganisationSetting.objects.filter(org_setting__id=organisation_id,setting_key=data["setting_key"]).first()
                if sms_setting:
                    sms_setting.setting_key=data["setting_key"]
                    sms_setting.setting_value = data["setting_value"]
                    sms_setting.setting_added_by=self.request.user.id
                    sms_setting.save()
                else:
                    OrganisationSetting.objects.create(setting_key=data["setting_key"],setting_value=data["setting_value"],org_setting=Organisation.objects.get(pk=organisation_id),setting_added_by=self.request.user.id)
            
            return Response({"message":"Success"})
       
        
class OrganisationSmsSubscriptionViewset(viewsets.ModelViewSet):
    serializer_class = OrganisationSmsSubscriptionSerializer
    filter_backends = (SearchFilter, OrderingFilter, DjangoFilterBackend, )

    def get_queryset(self):
        organisation_id = get_current_user(self.request, 'organisation_id', None)
        return OrganisationSmsSubscription.objects.filter(organisation__id = organisation_id).order_by('id')
    
    def perform_update(self, serializer):
        serializer.save(last_updated_by=self.request.user,last_updated=datetime.now())

class BulkSmsSubscriptionViewset(APIView):

    def get(self, request):
            organisation_id = get_current_user(self.request, 'organisation_id', None)
            process_type    = request.GET.get('process_type', None)
           
            if process_type   == 'send_sms': 
                search          = request.GET.get('search', None)
                filter_query    = {"org_subscription__organisation__id":organisation_id,"org_subscription__is_subscribed":True,"is_subscribed":True}
                member_sms_sub  = MemberSmsSubscription.objects.filter(Q(customer__name__icontains=search) | Q(customer__member_number__icontains=search)| Q(customer__old_member_number__icontains=search),**filter_query)
                subscribers     = MemberSmsSubscriptionSerializer(member_sms_sub, many=True).data
                return Response({"count":len(subscribers),"results":subscribers})
            
            if process_type   == 'fetch_single':
                customer_id     = request.GET.get('customer_id', None)
                organisation    = Organisation.objects.get(pk=organisation_id)
                subscriptions   = []
                organisation_sms_subs = OrganisationSmsSubscription.objects.filter(organisation=organisation,is_subscribed=True)
                
                if organisation_sms_subs and customer_id:
                    for organisation_sms_sub in organisation_sms_subs:
                        member_sms_sub = MemberSmsSubscription.objects.filter(org_subscription=organisation_sms_sub,customer__id=customer_id).first()
                        if not member_sms_sub:
                            subscriptions.append({"sms_type":organisation_sms_sub.sms_type.sms_type_name,"org_subscription_id":organisation_sms_sub.id,"is_subscribed":False})
                        else:
                            subscriptions.append({"sms_type":organisation_sms_sub.sms_type.sms_type_name,"org_subscription_id":organisation_sms_sub.id,"is_subscribed":member_sms_sub.is_subscribed})  
                return Response({"count":len(subscriptions),"results":subscriptions})
            
            if process_type   == 'fetch_bulk':
                subscriptions   = []
                is_subscribed  = request.GET.get('is_subscribed', None)
                sms_type_key   = request.GET.get('sms_type_key', None)
                if is_subscribed == 'True':
                    member_sms_subs = MemberSmsSubscription.objects.filter(org_subscription__sms_type__sms_type_key = sms_type_key, org_subscription__organisation__id=organisation_id,org_subscription__is_subscribed=True,is_subscribed=True).order_by('customer__name')
                    if member_sms_subs:
                        for member_sms_sub in member_sms_subs:
                            subscriptions.append({
                                "customer_name":member_sms_sub.customer.name,
                                "customer_id":member_sms_sub.customer.id,
                                "member_number":member_sms_sub.customer.member_number,
                                "sms_type_name":member_sms_sub.org_subscription.sms_type.sms_type_name,
                                "sms_type_key":member_sms_sub.org_subscription.sms_type.sms_type_key,
                                "org_subscription_id":member_sms_sub.org_subscription.id
                            }) 
                else:
                    org_sub = OrganisationSmsSubscription.objects.filter(sms_type__sms_type_key = sms_type_key,organisation__id = organisation_id,is_subscribed=True).first()
                    if org_sub:
                        customer_ids = MemberSmsSubscription.objects.filter(org_subscription__sms_type__sms_type_key = sms_type_key,org_subscription__organisation__id=organisation_id,org_subscription__is_subscribed=True,is_subscribed=True).values_list('customer__id', flat=True)
                        customers = Customer.objects.filter(customer_branch__branch_organisation__id=organisation_id).exclude(id__in=customer_ids)
                        if customers:
                            for customer in customers:
                                subscriptions.append({
                                    "customer_name":customer.name,
                                    "customer_id":customer.id,
                                    "sms_type_name":org_sub.sms_type.sms_type_name,
                                    "sms_type_key":org_sub.sms_type.sms_type_key,
                                    "org_subscription_id":org_sub.id
                                }) 
                return Response({"count":len(subscriptions),"results":subscriptions})
    
    def post(self, request):
        request_data    = request.data
        process_type    = request_data['process_type']
        
        if process_type == 'statuses':
            is_subscribed   = request_data['is_subscribed']
            organisation_id = get_current_user(self.request, 'organisation_id', None)
            organisation = Organisation.objects.get(pk=organisation_id)
            sms_types    = SMSTypes.objects.filter(charged_to = "Institution")
            if sms_types:
                for sms_type in sms_types:
                    organisation_sms_sub = OrganisationSmsSubscription.objects.filter(organisation=organisation,sms_type__sms_type_key =sms_type.sms_type_key).first()
                    if not organisation_sms_sub:
                        data = {"sms_type":sms_type,"organisation":organisation, "charge":sms_type.base_fee,"added_by":self.request.user, "last_updated_by":self.request.user,"is_subscribed":is_subscribed}
                        OrganisationSmsSubscription.objects.create(**data)
                    else:
                        organisation_sms_sub.is_subscribed = is_subscribed
                        organisation_sms_sub.last_updated_by=self.request.user
                        organisation_sms_sub.last_updated = datetime.now()
                        organisation_sms_sub.save()

        if process_type == 'process_single':
            telephone       = request_data['telephone']
            customer_id     = request_data['customer_id']
            subscriptions   = request_data['subscriptions']

            if telephone:
                customer = Customer.objects.get(pk=customer_id)
                if customer:
                    customer.telephone = telephone
                    customer.save()
            for subscription in subscriptions:
                member_sms_sub = MemberSmsSubscription.objects.filter(org_subscription__id=subscription['subscription_id'],customer__id=customer_id).first()
                if member_sms_sub:
                    member_sms_sub.is_subscribed       = subscription['is_subscribed']
                    member_sms_sub.sub_last_updated_by = self.request.user
                    member_sms_sub.save()
                else:
                    data = {"customer_id":customer_id,"org_subscription":OrganisationSmsSubscription.objects.get(pk=subscription['subscription_id']),"sub_added_by":self.request.user, "sub_last_updated_by":self.request.user,"is_subscribed":subscription['is_subscribed']}
                    MemberSmsSubscription.objects.create(**data)

        if process_type == 'proces_bulk':
            customer_ids   = request_data['customer_ids']
            sms_type_key   = request_data['sms_type_key']
            is_subscribed  = request_data['is_subscribed']
            organisation_id = get_current_user(self.request, 'organisation_id', None)
            if customer_ids:
                for customer_id in customer_ids:
                    member_sms_sub = MemberSmsSubscription.objects.filter(org_subscription__sms_type__sms_type_key=sms_type_key,customer__id=customer_id).first()
                    if member_sms_sub:
                        member_sms_sub.is_subscribed       = is_subscribed
                        member_sms_sub.sub_last_updated_by = self.request.user
                        member_sms_sub.save()
                    else:
                        org_sub = OrganisationSmsSubscription.objects.filter(sms_type__sms_type_key=sms_type_key,organisation__id = organisation_id).first()
                        data = {"customer_id":customer_id,"org_subscription":org_sub,"sub_added_by":self.request.user, "sub_last_updated_by":self.request.user,"is_subscribed":is_subscribed}
                        MemberSmsSubscription.objects.create(**data)
        return Response({"message":"Success"})

    
class MemberSmsSubscriptionViewset(viewsets.ModelViewSet):
    queryset = MemberSmsSubscription.objects.all()
    serializer_class = MemberSmsSubscriptionSerializer
    filter_backends = (SearchFilter, OrderingFilter, DjangoFilterBackend,)
    
    def get_queryset(self):
        show_send_sms = True
        is_subscribed = self.request.GET.get('is_subscribed', None)
        sms_type_key  = self.request.GET.get('sms_type_key', None)
        customer_id   = self.request.GET.get('customer_id', None)

        organisation_id = get_current_user(self.request, 'organisation_id', None)
        filter_data     = {"org_subscription__organisation__id":organisation_id,"org_subscription__is_subscribed":True,"org_subscription__sms_type__status":'active'}

        if sms_type_key:
            filter_data["org_subscription__sms_type__sms_type_key"] = sms_type_key

        if is_subscribed:
            filter_data["is_subscribed"] = is_subscribed
        
        if customer_id:
            filter_data["customer__id"] = customer_id

        if not is_subscribed:
            show_send_sms = False

        # If  sms sending disabled at organisation level, disable selection on frontend sms
        is_sms_on = OrganisationSetting.objects.filter(org_setting__id = organisation_id,setting_key ="is_sms_on",setting_value ="on").first()
        if not is_sms_on:
            show_send_sms = False

        # If manual sms selection disabled at organisation level, disable selection on frontend sms
        is_manual_selection_on = OrganisationSetting.objects.filter(org_setting__id = organisation_id,setting_key ="is_manual_selection_on",setting_value ="on").first()
        if not is_manual_selection_on:
            show_send_sms = False
            
        if show_send_sms == False:
            return MemberSmsSubscription.objects.filter(org_subscription__organisation__id=-1).order_by("-id")
        
        return MemberSmsSubscription.objects.filter(**filter_data).order_by("-id")

class UserSmsViewset(viewsets.ModelViewSet):
    serializer_class = UserSmsSerializer

    def get_queryset(self):
        branch_id       = get_current_user(self.request, 'organisation_branch_id', None)
        organisation_id = get_current_user(self.request, 'organisation_id', None)
        
        sms_key = self.request.GET.get('sms_key', None)
        start   = self.request.GET.get('s', None)
        end     = self.request.GET.get('e', None)

        filter_query  = {"branch__id":branch_id,"branch__branch_organisation__id":organisation_id,"date_added__date__lte":datetime.today().strftime("%Y-%m-%d")}
        if start: 
            filter_query["date_added__date__gte"] = start
        if end: 
            filter_query["date_added__date__lte"] = end
        if sms_key: 
            filter_query["sms_type__sms_type_key"] = sms_key

        return UserSms.objects.filter(**filter_query).order_by('-id')

    @action(detail=True, methods=['post'])
    def resend(self, request, pk=None):
        user_sms = UserSms.objects.filter(pk=pk).first()
        if not user_sms:
            return Response({'status': False, 'message': 'SMS record not found'}, status=status.HTTP_404_NOT_FOUND)
        response = send_sms(user_sms.telephone, user_sms.message)
        if response['status']:
            user_sms.is_sent = True
            user_sms.save()
        return Response(response, status=status.HTTP_200_OK)

class SendSMSViewset(APIView):
    def post(self, request, format=None):
        request_data = request.data
        sms_text     = request_data.get('sms_text')
        unique_key   = request_data.get('unique_key','')
        send_to      = request_data.get('send_to')
        send_type    = request_data.get('send_type')
        branches     = request_data.get('branches')
        
        branch_id    = get_current_user(self.request, 'organisation_branch_id', 1) 
        organisation_id = get_current_user(self.request, 'organisation_id', None)
        response_msg = "error occurred"

        if send_type == 'single':
            if send_to == 'other':
                telephone = request_data.get('phone_number')
                query_filters = Q()
                query_filters.add(Q(**{"telephone": telephone}), Q.OR)
                if '+' not in telephone:
                    if len(telephone) > 0:
                        if int(telephone[0]) == 0:
                            query_filters.add(Q(**{"telephone": '+256' + telephone[1:]}), Q.OR)
                            query_filters.add(Q(**{"telephone": '256' + telephone[1:]}), Q.OR)
                        if '256' in telephone[0:3]:
                            query_filters.add(Q(**{"telephone": '0' + telephone[4:]}), Q.OR)
                            query_filters.add(Q(**{"telephone":telephone[4:]}), Q.OR)
                    customer = Customer.objects.filter(query_filters).first()
                    if customer:
                        response = send_non_subscriber_single_sms(customer,self.request.user,branch_id,sms_text,unique_key)
                if response['status']:
                    return Response(response, status=status.HTTP_200_OK)
                return Response({"status":False,"message":response_msg}, status=status.HTTP_200_OK)
                
            if send_to == 'subscribed_member':
                subscribed_members = request_data.get('subscribed_member')
                sent_count = 0
                failed_responses = []
                if subscribed_members:
                    # for subscribed_member in subscribed_members:
                        customer = Customer.objects.get(pk=subscribed_members)
                        if customer:
                           response = send_customer_single_sms(customer,self.request.user,branch_id,sms_text,'')
                           if response['status']:
                                sent_count += 1
                           else:
                            failed_responses.append({"customer":customer.name,'response':response['comment']})
                return Response({"status":True,"message":{"sent":sent_count,"failed":failed_responses}} ,status=status.HTTP_200_OK)

        if send_type == 'bulk':
            include_non_subscribers = request_data.get('include_non_subscribers')
            if send_to == 'template':
                send_bulk_template_sms = threading.Thread(target=self.send_bulk_template_sms_thread, args=(request_data.get('phone_numbers'),request.user,branch_id,sms_text,unique_key,))
                send_bulk_template_sms.start()
            if send_to == 'customer_group':
                send_bulk_group_sms = threading.Thread(target=self.send_bulk_group_sms_thread, args=(request_data.get('customer_group'),request.user,branch_id,sms_text,unique_key,include_non_subscribers,))
                send_bulk_group_sms.start()
            if send_to == 'group_category':
                send_bulk_group_category_sms = threading.Thread(target=self.send_bulk_group_category_sms_thread, args=(request_data.get('group_category'),branches,organisation_id,request.user,branch_id,sms_text,unique_key,include_non_subscribers,))
                send_bulk_group_category_sms.start()
            if send_to == 'general':
                send_bulk_branches_sms = threading.Thread(target=self.send_bulk_branches_sms_thread, args=(branches,request.user,branch_id,sms_text,unique_key,include_non_subscribers,))
                send_bulk_branches_sms.start()
            return Response({"status":True} ,status=status.HTTP_200_OK)

    def _extract_selected_ids(self, values):
            ids = []
            if values:
                for value in values:
                    if isinstance(value, dict):
                        value = value.get('id') or value.get('group_category_id') or value.get('value')
                    if value not in [None, '']:
                        ids.append(str(value).strip())
            return ids

    def _get_bulk_customer_dedupe_key(self, customer):
            if not customer:
                return None

            if customer.id not in [None, '']:
                return f"customer:{customer.id}"

            if customer.telephone not in [None, '']:
                return f"phone:{str(customer.telephone).strip()}"

            return None

    def _send_bulk_customer_sms(self, customer, user, branch_id, sms_text, unique_key, include_non_subscribers, sent_recipient_keys=None):
            if not customer or not customer.telephone:
                return

            if sent_recipient_keys is not None:
                recipient_key = self._get_bulk_customer_dedupe_key(customer)
                if recipient_key and recipient_key in sent_recipient_keys:
                    return
                if recipient_key:
                    sent_recipient_keys.add(recipient_key)

            user_sms = UserSms.objects.filter(telephone=customer.telephone, sms_unique_key=unique_key)
            if user_sms:
                return

            customer_sms_text = sms_text
            customer_sms_text = customer_sms_text.replace("[NAME]", customer.name)
            customer_sms_text = customer_sms_text.replace("[MEM_NO]", customer.member_number)
            subscriber_data = is_customer_subscriber('customer_single_sms', customer, branch_id)
            if subscriber_data['is_subscribed']:
                send_customer_single_sms(customer, user, branch_id, customer_sms_text, unique_key)
            else:
                if include_non_subscribers:
                    response = send_non_subscriber_single_sms(customer, user, branch_id, customer_sms_text, unique_key)
                    if response['status']:
                        user_sms = UserSms.objects.filter(telephone=customer.telephone, message=customer_sms_text).order_by('-id').first()
                        if user_sms:
                            user_sms.sms_unique_key = unique_key
                            user_sms.save()

    def _extract_phone_numbers(self, values):
            phone_numbers = []
            seen = set()
            if values:
                for value in values:
                    if isinstance(value, dict):
                        value = value.get('phone_number') or value.get('telephone') or value.get('value')
                    if value not in [None, '']:
                        telephone = str(value).strip()
                        if telephone and telephone not in seen:
                            seen.add(telephone)
                            phone_numbers.append(telephone)
            return phone_numbers

    def send_bulk_group_sms_thread(self,groups,user, branch_id,sms_text,unique_key,include_non_subscribers):
            try:
                group_ids = self._extract_selected_ids(groups)
                if group_ids:
                    memberships = GroupMembership.objects.filter(group__id__in=group_ids, active=True).select_related('member')
                    for membership in memberships:
                        self._send_bulk_customer_sms(membership.member, user, branch_id, sms_text, unique_key, include_non_subscribers)
            except Exception as e:
                print(e)
                raise Http404

    def send_bulk_group_category_sms_thread(self, group_categories, branches, organisation_id, user, branch_id, sms_text, unique_key, include_non_subscribers):
            try:
                group_category_ids = self._extract_selected_ids(group_categories)
                branch_ids = self._extract_selected_ids(branches)
                if group_category_ids:
                    sent_recipient_keys = set()
                    customers = Customer.objects.filter(
                        customer_branch__branch_organisation__id=organisation_id,
                        group_category__id__in=group_category_ids,
                    )
                    if branch_ids:
                        customers = customers.filter(customer_branch__id__in=branch_ids)
                    for customer in customers.distinct():
                        self._send_bulk_customer_sms(customer, user, branch_id, sms_text, unique_key, include_non_subscribers, sent_recipient_keys=sent_recipient_keys)
            except Exception as e:
                print(e)
                raise Http404

    def send_bulk_template_sms_thread(self, phone_numbers, user, branch_id, sms_text, unique_key):
            try:
                bulk_phone_numbers = self._extract_phone_numbers(phone_numbers)
                if bulk_phone_numbers:
                    for phone_number in bulk_phone_numbers:
                        send_external_single_sms(phone_number, user, branch_id, sms_text, unique_key)
            except Exception as e:
                print(e)
                raise Http404
    
    def send_bulk_branches_sms_thread(self,branches,user, branch_id,sms_text,unique_key,include_non_subscribers):
            try:
                if branches:
                    for branch in branches:
                        branchs = OrganisationBranch.objects.get(pk=branch)
                        if branchs:
                            branch_customers =  Customer.objects.filter(customer_branch__id=branch,status='active')
                            if branch_customers:
                                for branch_customer in branch_customers:
                                    user_sms = UserSms.objects.filter(telephone=branch_customer.telephone,sms_unique_key=unique_key,is_sent=True)
                                    
                                    if not user_sms:
                                        customer_sms_text = sms_text
                                        customer_sms_text = customer_sms_text.replace("[NAME]",branch_customer.name)
                                        customer_sms_text = customer_sms_text.replace("[MEM_NO]",branch_customer.member_number)
                                        subscriber_data  = is_customer_subscriber('customer_single_sms',branch_customer,branch_id)
                                        if subscriber_data['is_subscribed']:
                                            send_customer_single_sms(branch_customer,user,branch_id,customer_sms_text,unique_key)
                                        else:
                                            if include_non_subscribers:
                                                response = send_non_subscriber_single_sms(branch_customer,user,branch_id,customer_sms_text,unique_key)
                                                # Update the sms key for non subscriber
                                                if response['status']:
                                                    user_sms = UserSms.objects.filter(telephone=branch_customer.telephone,message=customer_sms_text,is_sent=True).order_by('-id')[0]
                                                    if user_sms:
                                                        user_sms.sms_unique_key = unique_key
                                                        user_sms.save()
                                                

                                       
                                    
            except Exception as e:
                print(e)
                raise Http404
