from rest_framework import status, viewsets
from rest_framework.response import Response
from .serializers import AppointmentsSerializer
from .models import Appointments
from rest_framework.permissions import AllowAny
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter
from .tasks import send_emails
import logging, re
from datetime import datetime, time, timezone
from activity_logs.models import ActivityLogs
from users.permissions import IsAdminOrMaintainer

logging.basicConfig(
    level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)


# Create your views here.
class AppointmentsViewset(viewsets.ModelViewSet):
    queryset = Appointments.objects.order_by("-created_at")
    serializer_class = AppointmentsSerializer
    filter_backends = [DjangoFilterBackend, SearchFilter]
    search_fields = [
        "first_name",
        "last_name",
        "email",
        "contact_number",
        "remarks",
        "company_name",
    ]
    filterset_fields = ["branch", "remarks"]

    def get_serializer_context(self):
        method = self.request.method

        context = super().get_serializer_context()
        context["method"] = method

        return context

    def get_permissions(self):
        method = self.request.method

        if method == "POST":
            return [AllowAny()]

        return [IsAdminOrMaintainer()]

    def is_datetime_iso8601_z_format(self, dt_string):
        pattern = r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$"
        return bool(re.match(pattern, dt_string))

    def create(self, request, *args, **kwargs):
        data = request.data
        scheduled_date_time = data["scheduled_date_time"]
        branch = data["branch"]

        is_datetime_iso8601_z_format = self.is_datetime_iso8601_z_format(
            dt_string=scheduled_date_time
        )

        if is_datetime_iso8601_z_format:
            scheduled_dt = datetime.strptime(
                scheduled_date_time, "%Y-%m-%dT%H:%M:%S.%fZ"
            ).replace(tzinfo=timezone.utc)
            scheduled_time = scheduled_dt.time()
            start_time = time(10, 0)
            end_time = time(16, 0)
        else:
            scheduled_dt = datetime.fromisoformat(scheduled_date_time)
            scheduled_time = scheduled_dt.time()
            start_time = datetime.strptime("10:00", "%H:%M").time()
            end_time = datetime.strptime("16:00", "%H:%M").time()

        scheduled_day = scheduled_dt.strftime("%A")

        if scheduled_time < start_time or scheduled_time > end_time:
            return Response(
                {"message": "Can only appoint from 10:00 AM to 4:00 PM."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        if branch.lower() in ["qc", "quezon city"] and scheduled_day.lower() in [
            "sat",
            "saturday",
        ]:
            return Response(
                {
                    "message": "Appointment in QC branch is only available from Monday to Friday, 10:00 AM to 4:00 PM."
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        serializer = self.serializer_class(data=data)
        serializer.is_valid(raise_exception=True)
        validated_data = serializer.validated_data

        logging.info("Creating new appointment object")
        scheduled_appointment = Appointments.objects.create(**validated_data)

        scheduled_appointment_details = {
            "first_name": scheduled_appointment.first_name,
            "last_name": scheduled_appointment.last_name,
            "email": scheduled_appointment.email,
            "contact_number": scheduled_appointment.contact_number,
            "company_name": getattr(scheduled_appointment, "company_name", "N/A"),
            "branch": scheduled_appointment.branch,
            "date_and_time": scheduled_appointment.scheduled_date_time,
        }
        send_emails.delay(scheduled_appointment=scheduled_appointment_details)

        return Response(
            {"message": f"Appointment was scheduled successfully."},
            status=status.HTTP_201_CREATED,
        )

    def update(self, request, *args, **kwargs):
        data = request.data
        new_remarks = data["remarks"]
        instance = self.get_object()
        old_remarks = instance.remarks

        if old_remarks is None or old_remarks == "":
            old_remarks = "pending"

        action = f"Changed from status {old_remarks.lower()} to {new_remarks.lower()}"
        ActivityLogs.record_activity(user=request.user, action=action)
        return super().update(request, *args, **kwargs)
