
from .models import TelehealthBooking, TelehealthProvider, TelehealthAvailabilitySlot
from django import forms
from django.utils import timezone
from datetime import timedelta
from .models import Enquiry, CareerApplication
from .models import PaymentTransaction

class EnquiryForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            css = field.widget.attrs.get("class", "")
            field.widget.attrs["class"] = (css + " input").strip()

    class Meta:
        model = Enquiry
        fields = [
            "full_name", "phone", "email",
            "enquiry_type", "location", "preferred_contact_time",
            "message"
        ]
        widgets = {
            "message": forms.Textarea(attrs={"rows": 5}),
        }

class CareerApplicationForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            css = field.widget.attrs.get("class", "")
            field.widget.attrs["class"] = (css + " input").strip()

    class Meta:
        model = CareerApplication
        fields = ["position", "full_name", "phone", "email", "cv", "notes"]
        widgets = {
            "notes": forms.Textarea(attrs={"rows": 4}),
        }


from .models import CareRequest, CaregiverProfile, CareAssignment, TelehealthBooking

class CareRequestStep1Form(forms.Form):
    full_name = forms.CharField(max_length=140)
    phone = forms.CharField(max_length=30)
    email = forms.EmailField(required=False)
    location = forms.CharField(max_length=160, required=False)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for _, field in self.fields.items():
            field.widget.attrs["class"] = (field.widget.attrs.get("class","") + " input").strip()

class CareRequestStep2Form(forms.Form):
    request_type = forms.ChoiceField(choices=CareRequest.REQUEST_TYPES)
    patient_age = forms.IntegerField(required=False, min_value=0)
    care_needs = forms.CharField(widget=forms.Textarea(attrs={"rows": 4}))
    schedule_notes = forms.CharField(max_length=220, required=False)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for _, field in self.fields.items():
            field.widget.attrs["class"] = (field.widget.attrs.get("class","") + " input").strip()

class CareRequestStep3Form(forms.Form):
    preferred_start_date = forms.DateField(required=False, widget=forms.DateInput(attrs={"type":"date"}))
    preference_notes = forms.CharField(required=False, widget=forms.Textarea(attrs={"rows": 3}))
    risk_notes = forms.CharField(required=False, widget=forms.Textarea(attrs={"rows": 3}))

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for _, field in self.fields.items():
            field.widget.attrs["class"] = (field.widget.attrs.get("class","") + " input").strip()



class TelehealthSlotBookingForm(forms.Form):
    full_name = forms.CharField(max_length=140)
    phone = forms.CharField(max_length=30)
    email = forms.EmailField(required=False)
    consultation_mode = forms.ChoiceField(choices=TelehealthBooking.CONSULTATION_MODES, required=True)

    # selected slot id from calendar
    slot_id = forms.IntegerField(widget=forms.HiddenInput(), required=True)

    symptoms_or_reason = forms.CharField(
        required=False,
        widget=forms.Textarea(attrs={"rows": 4, "placeholder": "Describe symptoms / reason for consultation..."}),
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for _, field in self.fields.items():
            css = field.widget.attrs.get("class", "")
            # keep hidden input clean
            if isinstance(field.widget, forms.HiddenInput):
                field.widget.attrs["class"] = (css + " ").strip()
            else:
                field.widget.attrs["class"] = (css + " input").strip()


class TelehealthBookingForm(forms.ModelForm):
    class Meta:
        model = TelehealthBooking
        fields = ["full_name", "phone", "email", "consultation_mode", "preferred_date", "preferred_time", "symptoms_or_reason"]
        widgets = {
            "preferred_date": forms.DateInput(attrs={"type": "date"}),
            "preferred_time": forms.TextInput(attrs={"placeholder": "e.g., 10:00am – 11:00am"}),
            "symptoms_or_reason": forms.Textarea(attrs={"rows": 4, "placeholder": "Describe symptoms / reason for consultation..."}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for _, field in self.fields.items():
            css = field.widget.attrs.get("class", "")
            field.widget.attrs["class"] = (css + " input").strip()


class CaregiverAvailabilityForm(forms.ModelForm):
    class Meta:
        model = CaregiverProfile
        fields = ["phone", "location", "skills", "availability", "is_active"]
        widgets = {
            "skills": forms.Textarea(attrs={"rows": 3}),
            "availability": forms.Textarea(attrs={"rows": 3}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for _, field in self.fields.items():
            css = field.widget.attrs.get("class", "")
            field.widget.attrs["class"] = (css + " input").strip()

class AssignmentCreateForm(forms.ModelForm):
    class Meta:
        model = CareAssignment
        fields = ["care_request", "caregiver", "status", "start_date", "end_date", "notes"]
        widgets = {"notes": forms.Textarea(attrs={"rows": 3}),
                   "start_date": forms.DateInput(attrs={"type":"date"}),
                   "end_date": forms.DateInput(attrs={"type":"date"})}

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for _, field in self.fields.items():
            css = field.widget.attrs.get("class", "")
            field.widget.attrs["class"] = (css + " input").strip()


# -----------------------------------------------------------------------------
# Support Ticket Forms
# -----------------------------------------------------------------------------
class SupportTicketForm(forms.Form):
    full_name = forms.CharField(max_length=120, widget=forms.TextInput(attrs={"placeholder":"Your name"}))
    phone = forms.CharField(max_length=40, required=False, widget=forms.TextInput(attrs={"placeholder":"Phone (optional)"}))
    email = forms.EmailField(required=False, widget=forms.EmailInput(attrs={"placeholder":"Email (optional)"}))
    subject = forms.CharField(max_length=180, required=False, widget=forms.TextInput(attrs={"placeholder":"Subject (optional)"}))
    message = forms.CharField(widget=forms.Textarea(attrs={"placeholder":"How can we help?"}))


from .models import EMRNote

class EMRNoteForm(forms.ModelForm):
    class Meta:
        model = EMRNote
        fields = ["title", "note"]
        widgets = {"note": forms.Textarea(attrs={"rows": 5})}

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for _, field in self.fields.items():
            field.widget.attrs["class"] = (field.widget.attrs.get("class", "") + " input").strip()



# ===========================
# Staff management forms
# ===========================
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group

User = get_user_model()

class TelehealthBookingStaffForm(forms.ModelForm):
    """
    Staff/admin form for editing TelehealthBooking.

    NOTE:
    - TelehealthBooking model does NOT have `provider` or `mode`.
    - Provider is selected through TelehealthAvailabilitySlot (slot -> provider).
    - consultation_mode is the correct field (not "mode").
    """

    provider = forms.ModelChoiceField(
        queryset=TelehealthProvider.objects.filter(is_active=True).order_by("sort_order", "full_name"),
        required=False,
        help_text="Optional: choose a provider to filter the available slots."
    )

    class Meta:
        model = TelehealthBooking
        fields = [
            "status",
            "provider",             # virtual (not stored on TelehealthBooking)
            "slot",                 # stored FK to availability slot
            "consultation_mode",    # stored (video/phone/chat)
            "full_name",
            "phone",
            "email",
            "symptoms_or_reason",
            "fee_ngn",
            "is_paid",
            "paystack_reference",
        ]
        widgets = {
            "symptoms_or_reason": forms.Textarea(attrs={"rows": 4}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        slots_qs = TelehealthAvailabilitySlot.objects.filter(is_active=True).order_by("start_at")

        provider_id = None
        if self.data.get("provider"):
            provider_id = self.data.get("provider")
        elif self.instance and getattr(self.instance, "slot_id", None):
            try:
                provider_id = self.instance.slot.provider_id
            except Exception:
                provider_id = None

        if provider_id:
            slots_qs = slots_qs.filter(provider_id=provider_id)

        self.fields["slot"].queryset = slots_qs

        # Pre-fill provider on edit
        if self.instance and getattr(self.instance, "slot_id", None) and not self.data.get("provider"):
            try:
                self.fields["provider"].initial = self.instance.slot.provider
            except Exception:
                pass

class TelehealthAvailabilitySlotForm(forms.ModelForm):
    """
    Form for admin-managed telehealth availability slots.

    Model fields are:
      - provider (FK)
      - start_at (DateTimeField)
      - end_at (DateTimeField)
      - capacity, is_active
    """
    class Meta:
        model = TelehealthAvailabilitySlot
        fields = ["provider", "start_at", "end_at", "capacity", "is_active"]
        widgets = {
            "start_at": forms.DateTimeInput(format="%Y-%m-%dT%H:%M", attrs={"type": "datetime-local", "class": "input"}),
            "end_at": forms.DateTimeInput(format="%Y-%m-%dT%H:%M", attrs={"type": "datetime-local", "class": "input"}),
        }
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["provider"].queryset = TelehealthProvider.objects.filter(is_active=True).order_by("sort_order", "full_name")
        if not self.is_bound and not self.instance.pk:
            now = timezone.localtime()
            start = (now + timedelta(hours=1)).replace(minute=0, second=0, microsecond=0)
            self.initial.update({"start_at": start, "end_at": start + timedelta(minutes=60), "capacity": 1, "is_active": True})
        for key in ("start_at", "end_at"):
            self.fields[key].input_formats = ["%Y-%m-%dT%H:%M", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S"]
        for field in self.fields.values():
            field.widget.attrs.setdefault("class", "input")

    def clean(self):
        cleaned = super().clean()
        start, end = cleaned.get("start_at"), cleaned.get("end_at")
        if start and end:
            if end <= start:
                raise forms.ValidationError("End time must be after start time.")
            if not self.instance.pk and start < timezone.now():
                raise forms.ValidationError("New appointment slots must be in the future.")
            if end - start > timedelta(hours=12):
                raise forms.ValidationError("A single slot cannot exceed 12 hours.")
        return cleaned

class CareRequestStaffForm(forms.ModelForm):
    """Staff form for updating CareRequest status, assignment and notes."""
    class Meta:
        model = CareRequest
        fields = [
            "status",
            "assigned_to",
            "schedule_notes",
            "preference_notes",
            "risk_notes",
        ]
        widgets = {
            "preference_notes": forms.Textarea(attrs={"rows": 3}),
            "risk_notes": forms.Textarea(attrs={"rows": 3}),
        }

class CareerApplicationStaffForm(forms.ModelForm):
    class Meta:
        model = CareerApplication
        fields = ["status", "notes"]

class PaymentTransactionStaffForm(forms.ModelForm):
    class Meta:
        model = PaymentTransaction
        fields = ["status", "notes"]

STAFF_ROLE_NAMES = ("Doctor", "Nurse", "Caregiver", "Care Coordinator", "Receptionist", "HR Manager", "Admin")

class StaffUserForm(forms.ModelForm):
    role = forms.ChoiceField(choices=[(r, r) for r in STAFF_ROLE_NAMES], label="Staff role")

    class Meta:
        model = User
        fields = ["first_name", "last_name", "email", "is_active"]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.instance and self.instance.pk:
            existing = self.instance.groups.filter(name__in=STAFF_ROLE_NAMES).first()
            if existing:
                self.fields["role"].initial = existing.name

    def clean_email(self):
        email = self.cleaned_data["email"].strip()
        if not email:
            raise forms.ValidationError("Email is required for staff accounts.")
        qs = User.objects.filter(email__iexact=email)
        if self.instance.pk:
            qs = qs.exclude(pk=self.instance.pk)
        if qs.exists():
            raise forms.ValidationError("This email is already in use.")
        return email

    def save(self, commit=True):
        user = super().save(commit=False)
        user.is_staff = True
        if commit:
            user.save()
            role, _ = Group.objects.get_or_create(name=self.cleaned_data["role"])
            # Retain unrelated groups, but enforce exactly one operational role.
            user.groups.remove(*list(user.groups.filter(name__in=STAFF_ROLE_NAMES)))
            user.groups.add(role)
        return user

class StaffUserCreateForm(StaffUserForm):
    username = forms.CharField(max_length=150)
    password1 = forms.CharField(widget=forms.PasswordInput, min_length=12, help_text="Use a unique temporary password (12+ characters).")
    password2 = forms.CharField(widget=forms.PasswordInput)

    class Meta(StaffUserForm.Meta):
        fields = ["username"] + StaffUserForm.Meta.fields

    def clean_username(self):
        username = self.cleaned_data["username"].strip()
        if User.objects.filter(username__iexact=username).exists():
            raise forms.ValidationError("This username is already in use.")
        return username

    def clean(self):
        cleaned = super().clean()
        if cleaned.get("password1") and cleaned.get("password1") != cleaned.get("password2"):
            self.add_error("password2", "Passwords do not match.")
        return cleaned

    def save(self, commit=True):
        user = super().save(commit=False)
        user.username = self.cleaned_data["username"]
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
            role, _ = Group.objects.get_or_create(name=self.cleaned_data["role"])
            user.groups.add(role)
        return user


from .models import Service, BlogPost, CareerPosition

class _StaffModelFormMixin:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            css = field.widget.attrs.get("class", "")
            # keep checkbox/radio clean
            if field.widget.__class__.__name__ in ["CheckboxInput", "CheckboxSelectMultiple", "RadioSelect"]:
                continue
            field.widget.attrs["class"] = (css + " input").strip()

class ServiceForm(_StaffModelFormMixin, forms.ModelForm):
    class Meta:
        model = Service
        fields = ["title", "slug", "short_description", "who_its_for", "benefits", "icon", "is_featured", "sort_order"]
        widgets = {
            "short_description": forms.Textarea(attrs={"rows": 3}),
            "who_its_for": forms.Textarea(attrs={"rows": 3}),
            "benefits": forms.Textarea(attrs={"rows": 4}),
        }

class BlogPostForm(_StaffModelFormMixin, forms.ModelForm):
    class Meta:
        model = BlogPost
        fields = ["title", "slug", "excerpt", "body", "cover_image", "is_published", "published_at"]
        widgets = {
            "excerpt": forms.Textarea(attrs={"rows": 3}),
            "body": forms.Textarea(attrs={"rows": 10}),
            "published_at": forms.DateTimeInput(attrs={"type":"datetime-local"}),
        }

class CareerPositionForm(_StaffModelFormMixin, forms.ModelForm):
    class Meta:
        model = CareerPosition
        fields = ["title", "role_type", "description", "requirements", "is_active"]
        widgets = {
            "description": forms.Textarea(attrs={"rows": 5}),
            "requirements": forms.Textarea(attrs={"rows": 5}),
        }

    def save(self, commit=True):
        obj = super().save(commit=False)
        # Keep legacy public field `is_open` in sync with staff field `is_active`.
        if hasattr(obj, "is_open") and "is_active" in self.cleaned_data:
            obj.is_open = bool(self.cleaned_data.get("is_active"))
        if commit:
            obj.save()
            if hasattr(self, "save_m2m"):
                self.save_m2m()
        return obj


class StaffTelehealthProviderForm(forms.ModelForm):
    class Meta:
        model = TelehealthProvider
        fields = ['full_name','role','specialization','license_number','license_authority',
                  'working_days','work_start','work_end','slot_minutes','sort_order']
        widgets = {
            'work_start': forms.TimeInput(attrs={'type':'time'},format='%H:%M'),
            'work_end': forms.TimeInput(attrs={'type':'time'},format='%H:%M'),
        }
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        for field in self.fields.values():
            field.widget.attrs['class'] = 'input'
        for key in ('work_start','work_end'):
            self.fields[key].input_formats = ['%H:%M','%H:%M:%S']
    def clean(self):
        data = super().clean()
        days = (data.get('working_days') or '').split(',')
        if not days or any(d.strip() not in tuple(str(n) for n in range(7)) for d in days) or len(set(days)) != len(days):
            self.add_error('working_days','Use comma-separated weekdays 0–6, e.g. 0,1,2,3,4.')
        if data.get('work_start') and data.get('work_end') and data['work_start'] >= data['work_end']:
            self.add_error('work_end','End time must be after start time.')
        if data.get('slot_minutes') not in (15,20,30,45,60,90,120):
            self.add_error('slot_minutes','Choose 15, 20, 30, 45, 60, 90 or 120 minutes.')
        return data
