import csv
import io
import logging
from rest_framework import viewsets, status
from rest_framework.decorators import action, api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from django.http import HttpResponse

from django.db import transaction
from accounts.models import User
from .models import Lead, LeadContact, Task
from .serializers import *

logger = logging.getLogger('crm')

class LeadViewSet(viewsets.ModelViewSet):
    queryset = Lead.objects.all()
    search_fields = ['company_name', 'vertical', 'city', 'state', 'notes']
    ordering_fields = ['created_at', 'company_name', 'status', 'research_date']

    def get_serializer_class(self):
        if self.action == 'retrieve':
            return LeadDetailSerializer
        return LeadSerializer

    def get_queryset(self):
        qs = super().get_queryset()
        params = self.request.query_params
        if params.get('status'):
            qs = qs.filter(status=params['status'])
        if params.get('vertical'):
            qs = qs.filter(vertical__icontains=params['vertical'])
        if params.get('assigned_to'):
            qs = qs.filter(assigned_to_id=params['assigned_to'])
        if params.get('city'):
            qs = qs.filter(city__icontains=params['city'])
        if params.get('state'):
            qs = qs.filter(state__icontains=params['state'])
        return qs

    def perform_create(self, serializer):
        serializer.save(created_by=self.request.user)

    # POST /api/crm/leads/{id}/contacts/
    @action(detail=True, methods=['post', 'get'], url_path='contacts')
    def contacts(self, request, pk=None):
        lead = self.get_object()
        if request.method == 'GET':
            serializer = LeadContactSerializer(lead.contacts.all(), many=True)
            return Response(serializer.data)
        serializer = LeadContactSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save(lead=lead)
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    # POST /api/crm/leads/{id}/tasks/
    @action(detail=True, methods=['post', 'get'], url_path='tasks')
    def tasks(self, request, pk=None):
        lead = self.get_object()
        if request.method == 'GET':
            serializer = TaskSerializer(lead.tasks.all(), many=True)
            return Response(serializer.data)
        serializer = TaskSerializer(data={**request.data, 'lead': lead.id})
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    # PATCH /api/crm/leads/{id}/convert/
    @action(detail=True, methods=['patch'], url_path='convert')
    def convert(self, request, pk=None):
        lead = self.get_object()
        lead.status = Lead.Status.CONVERTED
        lead.save(update_fields=['status', 'updated_at'])
        return Response(LeadSerializer(lead).data)

    # POST /api/crm/leads/import-csv/
    @action(detail=False, methods=['post'], url_path='import-csv')
    def import_csv(self, request):
        logger.info(f"CSV import started by user {request.user}")
        serializer = CSVImportSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        csv_file = serializer.validated_data['file']

        if not csv_file.name.endswith('.csv'):
            logger.warning(f"Invalid file type uploaded by {request.user}: {csv_file.name}")
            return Response({'error': 'File must be a CSV'}, status=status.HTTP_400_BAD_REQUEST)

        file_data = csv_file.read()

        # Try safe decoding
        try:
            decoded = file_data.decode('utf-8-sig')  # handles Excel UTF-8 with BOM
        except UnicodeDecodeError:
            decoded = file_data.decode('latin-1')    # fallback for Windows encoding

        # Clean hidden characters like \xa0
        decoded = decoded.replace('\xa0', ' ')

        reader = csv.DictReader(io.StringIO(decoded))

        # Build a lookup: user name/email -> user id
        users = {u.email.lower(): u for u in User.objects.all()}
        user_names = {}
        for u in users.values():
            full = f"{u.first_name} {u.last_name}".strip().lower()
            if full:
                user_names[full] = u

        def safe_int(val):
            try:
                return int(val)
            except (ValueError, TypeError):
                return None

        def parse_date(val):
            if not val:
                return None
            from datetime import datetime
            for fmt in ('%d-%b-%y', '%d-%b-%Y', '%m/%d/%Y', '%m-%d-%Y', '%Y-%m-%d', '%d-%m-%Y', '%d/%m/%Y'):
                try:
                    return datetime.strptime(val, fmt).date()
                except ValueError:
                    continue
            return None
        

        created_count = 0
        errors = []

        with transaction.atomic():
            for row_num, row in enumerate(reader, start=2):
                row = {k.strip(): v.strip() if v else '' for k, v in row.items()}
                # print(f"Row {row_num} - Research Date raw value: '{row.get('Research Date')}'")
                # print(f"Row {row_num} - Parsed date: {parse_date(row.get('Research Date'))}")


                assigned_user = None
                assigned_val = row.get('Assigned To', '').lower()
                if assigned_val:
                    assigned_user = users.get(assigned_val) or user_names.get(assigned_val)

                try:
                    lead = Lead.objects.create(
                        assigned_to=assigned_user,
                        research_date=parse_date(row.get('Research Date')),
                        vertical=row.get('Vertical', ''),
                        city=row.get('City', ''),
                        state=row.get('State', ''),
                        country=row.get('Country', '') or 'India',
                        company_name=row.get('Company Name', '') or 'Unknown',
                        website=row.get('Website', ''),
                        google_maps_url=row.get('Google Maps URL', ''),
                        linkedin_url=row.get('LinkedIn URL', ''),
                        instagram_url=row.get('Instagram URL', ''),
                        branches=row.get('Branches', ''),
                        google_reviews=row.get('Google Reviews', ''),
                        website_quality=safe_int(row.get('Website Quality (1-10)')),
                        seo_opportunity=safe_int(row.get('SEO Opportunity (1-10)')),
                        chatbot_opportunity=safe_int(row.get('Chatbot Opportunity (1-10)')),
                        budget_fit=safe_int(row.get('Budget Fit (1-5)')),
                        decision_speed=safe_int(row.get('Decision Speed (1-5)')),
                        offer_fit=safe_int(row.get('Offer Fit (1-5)')),
                        personalization_note=row.get('Personalization Note', ''),
                        priority_score=safe_int(row.get('Priority Score')),
                        lead_tier=row.get('Lead Tier', ''),
                        current_stage=row.get('Current Stage', ''),
                        next_action=row.get('Next Action', ''),
                        next_action_date=parse_date(row.get('Next Action Date')),
                        source=row.get('Source', ''),
                        status='new',
                        notes=row.get('Notes', ''),
                        created_by=request.user,
                    )

                    contact_name = row.get('Contact Name', '')
                    if contact_name:
                        LeadContact.objects.create(
                            lead=lead,
                            name=contact_name,
                            role=row.get('Role', ''),
                            phone=row.get('Phone', ''),
                            email=row.get('Email', ''),
                        )

                    created_count += 1
                except Exception as e:
                    logger.error(f"CSV import row {row_num} failed: {e}")
                    errors.append({'row': row_num, 'error': str(e)})

        logger.info(f"CSV import completed: {created_count} created, {len(errors)} errors")
        return Response({
            'created': created_count,
            'errors': errors,
        }, status=status.HTTP_201_CREATED)
        
    # POST /api/leads/check-lead/
    @action(detail=False, methods=['post'], url_path='check-lead')
    def check_lead(self, request):
        company_name = request.data.get('company_name', '').strip()
        name = request.data.get('name', '').strip()
        email = request.data.get('email', '').strip()

        if not any([company_name, name, email]):
            return Response({'error': 'Provide at least one of: company_name, name, email'}, status=status.HTTP_400_BAD_REQUEST)

        lead = None

        if company_name:
            lead = Lead.objects.filter(company_name__iexact=company_name).first()

        if not lead and email:
            contact = LeadContact.objects.filter(email__iexact=email).select_related('lead').first()
            if contact:
                lead = contact.lead

        if not lead and name:
            contact = LeadContact.objects.filter(name__iexact=name).select_related('lead').first()
            if contact:
                lead = contact.lead

        if not lead:
            return Response({'exists': False, 'message': 'No matching lead found'}, status=status.HTTP_200_OK)

        return Response({'exists': True, 'data': LeadDetailSerializer(lead).data}, status=status.HTTP_200_OK)
    @action(detail=False, methods=['get'], url_path='search-by-contact')
    def search_by_contact(self, request):
        contact_name = request.query_params.get('contact_name', '')
        email = request.query_params.get('email', '')
        company = request.query_params.get('company', '')
        
        if not any([contact_name, email, company]):
            return Response(
                {'error': 'Provide at least one: contact_name, email, or company'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # Search in LeadContact
        contacts = LeadContact.objects.select_related('lead', 'lead__created_by')
        
        if contact_name:
            contacts = contacts.filter(name__icontains=contact_name)
        if email:
            contacts = contacts.filter(email__icontains=email)
        if company:
            contacts = contacts.filter(lead__company_name__icontains=company)
        
        results = []
        for contact in contacts:
            lead = contact.lead
            results.append({
                'contact_name': contact.name,
                'contact_email': contact.email,
                'contact_phone': contact.phone,
                'contact_role': contact.role,
                'company_name': lead.company_name,
                'vertical': lead.vertical,
                'service':lead.service,
                'source': lead.source,
                'status': lead.status,
                'notes': lead.notes,
                'personalization_note': lead.personalization_note,
                'created_by': lead.created_by.email if lead.created_by else None,
                'created_at': lead.created_at.strftime('%d:%m:%y %H:%M:%S') if lead.created_at else None,
                'updated_at': lead.updated_at.strftime('%d:%m:%y %H:%M:%S') if lead.updated_at else None,
            })
        
        return Response(results)
    @action(detail=False, methods=['get'], url_path='export-csv')
    def export_csv(self, request):
        qs = self.get_queryset()
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="leads.csv"'

        writer = csv.writer(response)
        writer.writerow([
            'Company Name', 'Vertical', 'City', 'State', 'Country',
            'Status', 'Source', 'Assigned To', 'Priority Score', 'Lead Tier',
            'Website', 'Notes', 'Created At',
        ])
        for lead in qs:
            writer.writerow([
                lead.company_name, lead.vertical, lead.city, lead.state, lead.country,
                lead.status, lead.source,
                lead.assigned_to.email if lead.assigned_to else '',
                lead.priority_score, lead.lead_tier,
                lead.website, lead.notes,
                lead.created_at.strftime('%Y-%m-%d %H:%M'),
            ])
        return response




class LeadContactViewSet(viewsets.ModelViewSet):
    queryset = LeadContact.objects.select_related('lead')
    serializer_class = LeadContactSerializer
    search_fields = ['name', 'email', 'phone']

    def get_queryset(self):
        qs = super().get_queryset()
        if self.request.query_params.get('lead'):
            qs = qs.filter(lead_id=self.request.query_params['lead'])
        return qs


class TaskViewSet(viewsets.ModelViewSet):
    queryset = Task.objects.select_related('lead', 'assigned_to')
    serializer_class = TaskSerializer
    search_fields = ['title', 'lead__company_name']
    ordering_fields = ['due_date', 'priority', 'status', 'created_at']

    def get_queryset(self):
        qs = super().get_queryset()
        params = self.request.query_params
        if params.get('lead'):
            qs = qs.filter(lead_id=params['lead'])
        if params.get('status'):
            qs = qs.filter(status=params['status'])
        if params.get('priority'):
            qs = qs.filter(priority=params['priority'])
        if params.get('assigned_to'):
            qs = qs.filter(assigned_to_id=params['assigned_to'])
        return qs


class EmailTemplateViewSet(viewsets.ModelViewSet):
    queryset = EmailTemplate.objects.all()
    serializer_class = EmailTemplateSerializer

    def perform_create(self, serializer):
        serializer.save(created_by=self.request.user)
        logger.info(f"Email template '{serializer.instance.name}' created by {self.request.user}")


class EmailSequenceViewSet(viewsets.ModelViewSet):
    queryset = EmailSequence.objects.prefetch_related('steps')
    serializer_class = EmailSequenceSerializer

    def perform_create(self, serializer):
        serializer.save(created_by=self.request.user)
        logger.info(f"Email sequence '{serializer.instance.name}' created by {self.request.user}")


class EmailSequenceStepViewSet(viewsets.ModelViewSet):
    queryset = EmailSequenceStep.objects.select_related('sequence', 'template')
    serializer_class = EmailSequenceStepSerializer

    def get_queryset(self):
        qs = super().get_queryset()
        if self.request.query_params.get('sequence'):
            qs = qs.filter(sequence_id=self.request.query_params['sequence'])
        return qs


class BatchViewSet(viewsets.ModelViewSet):
    queryset = Batch.objects.all()
    serializer_class = BatchSerializer

    def perform_create(self, serializer):
        serializer.save(created_by=self.request.user)
        logger.info(f"Batch '{serializer.instance.name}' created by {self.request.user} with sequence id={serializer.instance.sequence_id}")

    @action(detail=True, methods=['get'], url_path='leads')
    def leads(self, request, pk=None):
        batch = self.get_object()
        serializer = BatchLeadSerializer(batch.batch_leads.all(), many=True)
        return Response(serializer.data)

    @action(detail=True, methods=['patch'], url_path='pause')
    def pause(self, request, pk=None):
        batch = self.get_object()
        batch.status = Batch.Status.PAUSED
        batch.save(update_fields=['status'])
        logger.info(f"Batch '{batch.name}' (id={batch.id}) paused by {request.user}")
        return Response({'status': 'paused'})

    @action(detail=True, methods=['patch'], url_path='resume')
    def resume(self, request, pk=None):
        batch = self.get_object()
        batch.status = Batch.Status.ACTIVE
        batch.save(update_fields=['status'])
        logger.info(f"Batch '{batch.name}' (id={batch.id}) resumed by {request.user}")
        return Response({'status': 'active'})


class EmailLogViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = EmailLog.objects.select_related('batch_lead', 'template')
    serializer_class = EmailLogSerializer

    def get_queryset(self):
        qs = super().get_queryset()
        if self.request.query_params.get('batch_lead'):
            qs = qs.filter(batch_lead_id=self.request.query_params['batch_lead'])
        if self.request.query_params.get('batch'):
            qs = qs.filter(batch_lead__batch_id=self.request.query_params['batch'])
        return qs
