"""SME-Hub onboarding forms (SP1).

These forms drive the public registration flow, the entrepreneur multi-step
profile wizard, business registration with embedded M&E baseline fields, and
the AIH affiliation step.  All forms use plain Django + Tailwind classes;
no crispy-forms dependency is required because the templates render fields
explicitly.
"""
from __future__ import annotations

from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError

from apps.core.countries import CountryChoiceField
from apps.smehub._shared.choices import (
    COUNTRIES,
    LANGUAGES,
    ORG_TYPES,
    SECTORS,
    SERVICE_OFFERINGS,
)
from apps.smehub.onboarding.models import (
    AIHAffiliation,
    Business,
    BusinessBaseline,
    BusinessStage,
    BuyerProfile,
    EntrepreneurProfile,
    Innovation,
    InvestorProfile,
    MentorProfile,
    PartnerProfile,
    RegistrationRecord,
    RevenueRange,
    ServiceProviderProfile,
    VettingRecord,
    VettingScore,
)

User = get_user_model()

INPUT_BASE = (
    "block w-full rounded-lg border border-ruforum-border bg-white px-3 py-2 "
    "text-sm text-ruforum-text shadow-sm placeholder-ruforum-text-muted/70 "
    "focus:border-ruforum-primary focus:outline-none focus:ring-1 focus:ring-ruforum-primary"
)
SELECT_BASE = INPUT_BASE
TEXTAREA_BASE = INPUT_BASE + " min-h-[7rem]"
CHECKBOX_BASE = "h-4 w-4 rounded border-ruforum-border text-ruforum-primary focus:ring-ruforum-primary"


def _select2_single(*, placeholder: str = "", required: bool = True) -> dict:
    """Common attrs for single-select widgets that should get select2 treatment."""
    attrs = {"class": SELECT_BASE, "data-s2": ""}
    if placeholder:
        attrs["data-s2-placeholder"] = placeholder
    return attrs


def _select2_multi(*, placeholder: str = "Pick one or more…") -> dict:
    return {"class": SELECT_BASE + " min-h-[2.5rem]", "data-s2": "", "data-s2-placeholder": placeholder}


# A leading blank choice gives select2 a placeholder + clear button.
COUNTRY_CHOICES = [("", "")] + COUNTRIES
SECTOR_CHOICES = [("", "")] + SECTORS
ORG_TYPE_CHOICES = [("", "")] + ORG_TYPES


# ---------------------------------------------------------------------------
# Public registration
# ---------------------------------------------------------------------------

class RegistrationForm(forms.Form):
    """FRSME-OBR001 / OBR003 / OBR004 / OBR005."""

    full_name = forms.CharField(max_length=255, widget=forms.TextInput(attrs={"class": INPUT_BASE}))
    email = forms.EmailField(widget=forms.EmailInput(attrs={"class": INPUT_BASE, "autocomplete": "email"}))
    password = forms.CharField(
        min_length=8,
        widget=forms.PasswordInput(attrs={"class": INPUT_BASE, "autocomplete": "new-password"}),
    )
    password_confirm = forms.CharField(
        min_length=8,
        widget=forms.PasswordInput(attrs={"class": INPUT_BASE, "autocomplete": "new-password"}),
    )
    country = CountryChoiceField(
        required=False,
        attrs=_select2_single(placeholder="Search country…"),
    )
    organisation = forms.CharField(
        max_length=255,
        required=False,
        widget=forms.TextInput(attrs={"class": INPUT_BASE}),
    )
    phone = forms.CharField(
        max_length=32,
        required=False,
        widget=forms.TextInput(attrs={"class": INPUT_BASE, "placeholder": "+256..."}),
    )
    role = forms.ChoiceField(
        choices=RegistrationRecord.Role.choices,
        widget=forms.Select(attrs=_select2_single(placeholder="Select your role")),
    )
    consent = forms.BooleanField(
        required=True,
        widget=forms.CheckboxInput(attrs={"class": CHECKBOX_BASE}),
        help_text="I agree to the RUFORUM SME-Hub terms of use.",
    )

    def clean_email(self):
        email = self.cleaned_data["email"].strip().lower()
        if User.objects.filter(email__iexact=email, is_active=True).exists():
            raise ValidationError(
                "An active account already uses this email address. "
                "Please log in or reset your password.",
            )
        return email

    def clean(self):
        cleaned = super().clean()
        pwd = cleaned.get("password")
        pwd2 = cleaned.get("password_confirm")
        if pwd and pwd2 and pwd != pwd2:
            self.add_error("password_confirm", "Passwords do not match.")
        if pwd:
            try:
                validate_password(pwd)
            except ValidationError as exc:
                self.add_error("password", exc)
        return cleaned


class ResendVerificationForm(forms.Form):
    email = forms.EmailField(widget=forms.EmailInput(attrs={"class": INPUT_BASE}))


# ---------------------------------------------------------------------------
# Entrepreneur profile wizard
# ---------------------------------------------------------------------------

class EntrepreneurProfileForm(forms.ModelForm):
    """Step 1 of the wizard — basic profile + optional RIMS match selection."""

    rims_match_application_id = forms.IntegerField(required=False, widget=forms.HiddenInput())
    rims_match_scholar_id = forms.IntegerField(required=False, widget=forms.HiddenInput())

    country = CountryChoiceField(
        required=False,
        attrs=_select2_single(placeholder="Search country…"),
    )

    class Meta:
        model = EntrepreneurProfile
        fields = ("country", "organisation", "phone", "bio", "photo")
        widgets = {
            "organisation": forms.TextInput(attrs={"class": INPUT_BASE}),
            "phone": forms.TextInput(attrs={"class": INPUT_BASE}),
            "bio": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 4}),
            "photo": forms.ClearableFileInput(attrs={"class": INPUT_BASE}),
        }


# ---------------------------------------------------------------------------
# Business registration  (FRSME-OBR021 → OBR025)
# ---------------------------------------------------------------------------

class BusinessRegistrationForm(forms.ModelForm):
    """Combined business + baseline form. The view splits the data on save."""

    fte_count = forms.IntegerField(min_value=0, initial=0, widget=forms.NumberInput(attrs={"class": INPUT_BASE}))
    pte_count = forms.IntegerField(min_value=0, initial=0, widget=forms.NumberInput(attrs={"class": INPUT_BASE}))
    revenue_range = forms.ChoiceField(
        choices=RevenueRange.choices,
        widget=forms.Select(attrs=_select2_single(placeholder="Pick a revenue range")),
    )
    primary_target_market = forms.CharField(
        max_length=255,
        required=False,
        widget=forms.TextInput(attrs={"class": INPUT_BASE}),
    )
    geographic_reach = forms.CharField(
        max_length=255,
        required=False,
        widget=forms.TextInput(attrs={"class": INPUT_BASE, "placeholder": "Comma-separated countries"}),
    )

    sector = forms.ChoiceField(
        choices=SECTOR_CHOICES,
        widget=forms.Select(attrs=_select2_single(placeholder="Pick a sector")),
    )
    country = CountryChoiceField(
        required=False,
        attrs=_select2_single(placeholder="Search country…"),
    )
    business_stage = forms.ChoiceField(
        choices=BusinessStage.choices,
        widget=forms.Select(attrs=_select2_single(placeholder="Pick a stage")),
    )

    class Meta:
        model = Business
        fields = (
            "name", "sector", "sub_sector", "business_stage",
            "founding_date", "country", "location", "description",
            "target_market", "logo",
        )
        widgets = {
            "name": forms.TextInput(attrs={"class": INPUT_BASE}),
            "sub_sector": forms.TextInput(attrs={"class": INPUT_BASE}),
            "founding_date": forms.DateInput(attrs={"class": INPUT_BASE, "type": "date"}),
            "location": forms.TextInput(attrs={"class": INPUT_BASE}),
            "description": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 4}),
            "target_market": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 3}),
            "logo": forms.ClearableFileInput(attrs={"class": INPUT_BASE}),
        }


# ---------------------------------------------------------------------------
# AIH affiliation  (FRSME-OBR030 → OBR034)
# ---------------------------------------------------------------------------

class AIHAffiliationForm(forms.ModelForm):
    rims_award_id = forms.IntegerField(required=False, widget=forms.HiddenInput())
    rims_scholar_id = forms.IntegerField(required=False, widget=forms.HiddenInput())

    class Meta:
        model = AIHAffiliation
        fields = ("institution", "nature", "programme_of_origin", "is_primary")
        widgets = {
            "institution": forms.Select(attrs=_select2_single(placeholder="Search RUFORUM institutions…")),
            "nature": forms.Select(attrs=_select2_single(placeholder="Pick affiliation nature")),
            "programme_of_origin": forms.TextInput(attrs={"class": INPUT_BASE}),
            "is_primary": forms.CheckboxInput(attrs={"class": CHECKBOX_BASE}),
        }


# ---------------------------------------------------------------------------
# Mentor / Investor / ServiceProvider / Partner / Buyer role profiles
# ---------------------------------------------------------------------------

class _RoleProfileFormBase(forms.ModelForm):
    country = CountryChoiceField(
        required=False,
        attrs=_select2_single(placeholder="Search country…"),
    )

    class Meta:
        fields = ("country", "organisation", "phone", "bio")
        widgets = {
            "organisation": forms.TextInput(attrs={"class": INPUT_BASE}),
            "phone": forms.TextInput(attrs={"class": INPUT_BASE}),
            "bio": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 4}),
        }


class MentorProfileForm(_RoleProfileFormBase):
    expertise_sectors = forms.MultipleChoiceField(
        required=False,
        choices=SECTORS,
        widget=forms.SelectMultiple(attrs=_select2_multi(placeholder="Pick sectors you mentor in")),
        help_text="Sectors you specialise in mentoring.",
    )
    languages = forms.MultipleChoiceField(
        required=False,
        choices=LANGUAGES,
        widget=forms.SelectMultiple(attrs=_select2_multi(placeholder="Pick languages you speak")),
        help_text="Languages you can mentor in.",
    )

    class Meta(_RoleProfileFormBase.Meta):
        model = MentorProfile
        fields = (*_RoleProfileFormBase.Meta.fields, "years_experience")
        widgets = {
            **_RoleProfileFormBase.Meta.widgets,
            "years_experience": forms.NumberInput(attrs={"class": INPUT_BASE, "min": 0}),
        }


class InvestorProfileForm(_RoleProfileFormBase):
    organisation_type = forms.ChoiceField(
        required=False,
        choices=ORG_TYPE_CHOICES,
        widget=forms.Select(attrs=_select2_single(placeholder="Pick an organisation type")),
    )

    class Meta(_RoleProfileFormBase.Meta):
        model = InvestorProfile
        fields = (*_RoleProfileFormBase.Meta.fields, "organisation_type")


class ServiceProviderProfileForm(_RoleProfileFormBase):
    services_offered = forms.MultipleChoiceField(
        required=False,
        choices=SERVICE_OFFERINGS,
        widget=forms.SelectMultiple(attrs=_select2_multi(placeholder="Pick services you offer")),
        help_text="Services your organisation provides to entrepreneurs.",
    )

    class Meta(_RoleProfileFormBase.Meta):
        model = ServiceProviderProfile


class PartnerProfileForm(_RoleProfileFormBase):
    organisation_type = forms.ChoiceField(
        required=False,
        choices=ORG_TYPE_CHOICES,
        widget=forms.Select(attrs=_select2_single(placeholder="Pick an organisation type")),
    )

    class Meta(_RoleProfileFormBase.Meta):
        model = PartnerProfile
        fields = (*_RoleProfileFormBase.Meta.fields, "organisation_type")


class BuyerProfileForm(_RoleProfileFormBase):
    sectors_sourced = forms.MultipleChoiceField(
        required=False,
        choices=SECTORS,
        widget=forms.SelectMultiple(attrs=_select2_multi(placeholder="Pick sectors you procure from")),
        help_text="Sectors your organisation procures from.",
    )

    class Meta(_RoleProfileFormBase.Meta):
        model = BuyerProfile


def _split_csv(value: str) -> list[str]:
    return [v.strip() for v in (value or "").split(",") if v.strip()]


# ---------------------------------------------------------------------------
# Admin actions  (FRSME-OBR018 / OBR019 / OBR020 / OBR029)
# ---------------------------------------------------------------------------

class RejectionReasonForm(forms.Form):
    reason = forms.CharField(
        widget=forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 3}),
        help_text="Explain why this submission is not accepted; the reason is sent to the user.",
    )


class MoreInfoMessageForm(forms.Form):
    message = forms.CharField(
        widget=forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 3}),
        help_text="Tell the user exactly what's missing.",
    )


class BulkVerifyForm(forms.Form):
    """Hidden ID list — populated by the queue template."""

    ids = forms.CharField(widget=forms.HiddenInput())

    def clean_ids(self):
        raw = self.cleaned_data["ids"] or ""
        ids = [int(x) for x in raw.split(",") if x.strip().isdigit()]
        if not ids:
            raise ValidationError("No entrepreneurs selected.")
        return ids


class BackendRegisterForm(forms.Form):
    full_name = forms.CharField(max_length=255, widget=forms.TextInput(attrs={"class": INPUT_BASE}))
    email = forms.EmailField(widget=forms.EmailInput(attrs={"class": INPUT_BASE}))
    role = forms.ChoiceField(
        choices=RegistrationRecord.Role.choices,
        widget=forms.Select(attrs=_select2_single(placeholder="Pick a role")),
    )
    country = CountryChoiceField(
        required=False,
        attrs=_select2_single(placeholder="Search country…"),
    )
    organisation = forms.CharField(max_length=255, required=False, widget=forms.TextInput(attrs={"class": INPUT_BASE}))
    phone = forms.CharField(max_length=32, required=False, widget=forms.TextInput(attrs={"class": INPUT_BASE}))
    initial_password = forms.CharField(
        required=False,
        widget=forms.PasswordInput(attrs={"class": INPUT_BASE}),
        help_text="Optional; if blank an unusable password is set and the user must reset.",
    )


# ---------------------------------------------------------------------------
# Innovation onboarding & vetting (Phase 6.1)
# ---------------------------------------------------------------------------


class InnovationDraftForm(forms.ModelForm):
    """Single-form fallback for create + edit (used by templates without HTMX wizard)."""

    country = CountryChoiceField(required=False, attrs=_select2_single(placeholder="Country"))

    class Meta:
        model = Innovation
        fields = [
            "title",
            "tagline",
            "description",
            "problem_statement",
            "solution_summary",
            "market_focus",
            "sector",
            "sub_sector",
            "country",
            "stage",
            "team_size",
            "team_summary",
            "cover_image",
            "pitch_deck",
            "business_model_canvas",
        ]
        widgets = {
            "title": forms.TextInput(attrs={"class": INPUT_BASE}),
            "tagline": forms.TextInput(attrs={"class": INPUT_BASE}),
            "description": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 4}),
            "problem_statement": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 3}),
            "solution_summary": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 3}),
            "market_focus": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 3}),
            "sector": forms.Select(choices=[("", "---")] + list(SECTORS), attrs=_select2_single(placeholder="Pick a sector")),
            "sub_sector": forms.TextInput(attrs={"class": INPUT_BASE}),
            "stage": forms.Select(attrs={"class": SELECT_BASE}),
            "team_size": forms.NumberInput(attrs={"class": INPUT_BASE, "min": 1}),
            "team_summary": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 3}),
        }


class EvaluatorAssignmentForm(forms.Form):
    evaluator = forms.ModelChoiceField(
        queryset=User.objects.none(),
        widget=forms.Select(attrs=_select2_single(placeholder="Choose an evaluator")),
    )
    due_at = forms.DateTimeField(
        required=False,
        widget=forms.DateTimeInput(attrs={"class": INPUT_BASE, "type": "datetime-local"}),
    )

    def __init__(self, *args, **kwargs):
        evaluator_qs = kwargs.pop("evaluator_qs", None)
        super().__init__(*args, **kwargs)
        if evaluator_qs is not None:
            self.fields["evaluator"].queryset = evaluator_qs


class VettingScoreForm(forms.Form):
    """Single-dimension scoring form. Repeated client-side per dimension."""

    dimension = forms.ChoiceField(
        choices=VettingScore.Dimension.choices,
        widget=forms.Select(attrs={"class": SELECT_BASE}),
    )
    score = forms.IntegerField(
        min_value=1,
        max_value=5,
        widget=forms.NumberInput(attrs={"class": INPUT_BASE, "min": 1, "max": 5}),
    )
    comments = forms.CharField(
        required=False,
        widget=forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 2}),
    )


class VettingRecommendationForm(forms.Form):
    recommendation = forms.ChoiceField(
        choices=VettingRecord.Recommendation.choices,
        widget=forms.Select(attrs={"class": SELECT_BASE}),
    )
    summary = forms.CharField(
        required=False,
        widget=forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 4}),
    )


class VettingDecisionForm(forms.Form):
    DECISION_CHOICES = (
        ("approve", "Approve"),
        ("revise", "Request revisions"),
        ("reject", "Reject"),
    )
    decision = forms.ChoiceField(
        choices=DECISION_CHOICES,
        widget=forms.Select(attrs={"class": SELECT_BASE}),
    )
    feedback = forms.CharField(
        required=False,
        widget=forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 3}),
        help_text="Required for revisions; optional for approve.",
    )
    reason = forms.CharField(
        required=False,
        widget=forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 3}),
        help_text="Required for rejection.",
    )

    def clean(self):
        cleaned = super().clean()
        decision = cleaned.get("decision")
        if decision == "revise" and not cleaned.get("feedback", "").strip():
            self.add_error("feedback", "Feedback is required when requesting revisions.")
        if decision == "reject" and not cleaned.get("reason", "").strip():
            self.add_error("reason", "Reason is required when rejecting.")
        return cleaned


class MeetingRequestForm(forms.Form):
    """Direct meeting request to a mentor (creates a MeetingRequest)."""

    meeting_time = forms.DateTimeField(
        required=False,
        widget=forms.DateTimeInput(
            attrs={"class": INPUT_BASE, "type": "datetime-local"},
        ),
        help_text="Propose a time (UTC). The mentor can confirm or suggest another.",
    )
    agenda = forms.CharField(
        widget=forms.Textarea(attrs={
            "class": TEXTAREA_BASE,
            "rows": 4,
            "placeholder": "What would you like to discuss? A clear agenda makes a yes more likely.",
        }),
    )


class MeetingRespondForm(forms.Form):
    """Mentor's accept / decline on a meeting request."""

    DECISION_CHOICES = (
        ("accept", "Accept"),
        ("decline", "Decline"),
    )
    decision = forms.ChoiceField(choices=DECISION_CHOICES, widget=forms.HiddenInput())
    meeting_link = forms.URLField(
        required=False,
        assume_scheme="https",
        widget=forms.URLInput(attrs={
            "class": INPUT_BASE,
            "placeholder": "https://meet.google.com/… (optional)",
        }),
        help_text="Share a call link when accepting.",
    )
    reason = forms.CharField(
        required=False,
        widget=forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 2}),
        help_text="Optional note sent back to the requester.",
    )
