"""SP5 investment forms — investors, funding calls, applications, pitch flow.

Multi-selects use ``data-select2`` attrs so the project's select2 init partial
enhances them automatically.
"""
from __future__ import annotations

from decimal import Decimal

from django import forms
from django.core.exceptions import ValidationError
from django.forms import inlineformset_factory

from apps.core.countries import CountryMultipleChoiceField
from apps.smehub._shared.choices import (
    BUSINESS_STAGES,
    COUNTRIES,
    SECTORS,
)
from apps.smehub.investment.models import (
    FundingApplication,
    FundingApplicationDocument,
    FundingCall,
    Investor,
    InvestorConnectionRequest,
    ManualFundingRecord,
)
from apps.smehub.onboarding.models import Business


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"
)
TEXTAREA_BASE = INPUT_BASE + " min-h-[7rem]"
SELECT_BASE = INPUT_BASE
CHECKBOX_BASE = "h-4 w-4 rounded border-ruforum-border text-ruforum-primary focus:ring-ruforum-primary"


def _s2_single(*, placeholder: str = "") -> dict:
    attrs = {"class": SELECT_BASE, "data-s2": ""}
    if placeholder:
        attrs["data-s2-placeholder"] = placeholder
    return attrs


def _s2_multi(*, placeholder: str) -> dict:
    return {
        "class": SELECT_BASE + " min-h-[2.5rem]",
        "data-s2": "",
        "data-s2-placeholder": placeholder,
    }


# ---------------------------------------------------------------------------
# Investor directory
# ---------------------------------------------------------------------------

class InvestorForm(forms.ModelForm):
    """Admin-side create / update form."""

    investment_focus = forms.MultipleChoiceField(
        choices=SECTORS,
        required=False,
        widget=forms.SelectMultiple(attrs=_s2_multi(placeholder="Sectors of interest")),
    )
    geographic_preference = CountryMultipleChoiceField(
        choices=COUNTRIES,
        required=False,
        widget=forms.SelectMultiple(attrs=_s2_multi(placeholder="Countries of focus")),
    )

    class Meta:
        model = Investor
        fields = [
            "org_name",
            "type",
            "description",
            "ticket_size_min",
            "ticket_size_max",
            "contact_email",
            "contact_phone",
            "website",
            "logo",
            "investment_focus",
            "geographic_preference",
        ]
        widgets = {
            "org_name": forms.TextInput(attrs={"class": INPUT_BASE}),
            "type": forms.Select(attrs=_s2_single(placeholder="Investor type")),
            "description": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 4}),
            "ticket_size_min": forms.NumberInput(attrs={"class": INPUT_BASE, "step": "0.01", "placeholder": "e.g. 10000"}),
            "ticket_size_max": forms.NumberInput(attrs={"class": INPUT_BASE, "step": "0.01", "placeholder": "e.g. 250000"}),
            "contact_email": forms.EmailInput(attrs={"class": INPUT_BASE}),
            "contact_phone": forms.TextInput(attrs={"class": INPUT_BASE}),
            "website": forms.URLInput(attrs={"class": INPUT_BASE, "placeholder": "https://"}),
        }
        help_texts = {
            "ticket_size_min": "USD. Smallest cheque you'll write.",
            "ticket_size_max": "USD. Must be ≥ the minimum.",
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.instance.pk:
            self.initial["investment_focus"] = self.instance.investment_focus
            self.initial["geographic_preference"] = self.instance.geographic_preference

    def clean(self):
        cleaned = super().clean()
        lo = cleaned.get("ticket_size_min")
        hi = cleaned.get("ticket_size_max")
        if lo and hi and lo > hi:
            self.add_error("ticket_size_max", "Maximum ticket size cannot be less than the minimum.")
        return cleaned


class InvestorSelfRegisterForm(InvestorForm):
    """Investor user self-registers their own profile (FRSME-INV002)."""

    class Meta(InvestorForm.Meta):
        fields = [f for f in InvestorForm.Meta.fields if f != "logo"] + ["logo"]


class InvestorRejectForm(forms.Form):
    reason = forms.CharField(
        widget=forms.Textarea(
            attrs={"class": TEXTAREA_BASE, "rows": 3, "placeholder": "Tell the investor why this was rejected"},
        ),
    )


class InvestorDeactivateForm(forms.Form):
    reason = forms.CharField(
        required=False,
        widget=forms.Textarea(
            attrs={"class": TEXTAREA_BASE, "rows": 3, "placeholder": "Optional context"},
        ),
    )


# ---------------------------------------------------------------------------
# Funding calls
# ---------------------------------------------------------------------------

class ReadinessThresholdConfigForm(forms.ModelForm):
    """FRSME-INV010 — admin editor for the active readiness thresholds."""

    class Meta:
        from apps.smehub.investment.models import ReadinessThresholdConfig

        model = ReadinessThresholdConfig
        fields = [
            "name",
            "verified_business_required",
            "baseline_required",
            "incubation_completion_required",
            "min_partnerships",
            "min_showcase_or_catalogue",
            "min_funding_events",
        ]
        widgets = {
            "name": forms.TextInput(attrs={"class": INPUT_BASE}),
            "verified_business_required": forms.CheckboxInput(attrs={"class": CHECKBOX_BASE}),
            "baseline_required": forms.CheckboxInput(attrs={"class": CHECKBOX_BASE}),
            "incubation_completion_required": forms.CheckboxInput(attrs={"class": CHECKBOX_BASE}),
            "min_partnerships": forms.NumberInput(attrs={"class": INPUT_BASE, "min": 0}),
            "min_showcase_or_catalogue": forms.NumberInput(attrs={"class": INPUT_BASE, "min": 0}),
            "min_funding_events": forms.NumberInput(attrs={"class": INPUT_BASE, "min": 0}),
        }


class FundingCallForm(forms.ModelForm):
    target_sectors = forms.MultipleChoiceField(
        choices=SECTORS,
        required=False,
        widget=forms.SelectMultiple(attrs=_s2_multi(placeholder="Target sectors")),
    )
    target_stages = forms.MultipleChoiceField(
        choices=BUSINESS_STAGES,
        required=False,
        widget=forms.SelectMultiple(attrs=_s2_multi(placeholder="Target business stages")),
    )
    target_countries = CountryMultipleChoiceField(
        choices=COUNTRIES,
        required=False,
        widget=forms.SelectMultiple(attrs=_s2_multi(placeholder="Eligible countries")),
    )

    class Meta:
        model = FundingCall
        fields = [
            "title",
            "type",
            "summary",
            "description",
            "amount_min",
            "amount_max",
            "application_deadline",
            "contact_email",
            "cover_image",
            "investor",
            "target_sectors",
            "target_stages",
            "target_countries",
            "min_full_time_staff",
            "require_incubation_complete",
        ]
        widgets = {
            "title": forms.TextInput(attrs={"class": INPUT_BASE}),
            "type": forms.Select(attrs=_s2_single(placeholder="Funding type")),
            "summary": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 3}),
            "description": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 6}),
            "amount_min": forms.NumberInput(attrs={"class": INPUT_BASE, "step": "0.01"}),
            "amount_max": forms.NumberInput(attrs={"class": INPUT_BASE, "step": "0.01"}),
            "min_full_time_staff": forms.NumberInput(attrs={"class": INPUT_BASE, "min": 0}),
            "require_incubation_complete": forms.CheckboxInput(attrs={"class": CHECKBOX_BASE}),
            "application_deadline": forms.DateTimeInput(
                attrs={"class": INPUT_BASE, "type": "datetime-local"},
            ),
            "contact_email": forms.EmailInput(attrs={"class": INPUT_BASE}),
            "investor": forms.Select(attrs=_s2_single(placeholder="Sponsoring investor (optional)")),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["investor"].queryset = Investor.objects.filter(
            verification_status=Investor.Status.VERIFIED,
        ).order_by("org_name")
        self.fields["investor"].required = False
        if self.instance.pk:
            self.initial["target_sectors"] = self.instance.target_sectors
            self.initial["target_stages"] = self.instance.target_stages
            self.initial["target_countries"] = self.instance.target_countries

    def clean(self):
        cleaned = super().clean()
        lo = cleaned.get("amount_min")
        hi = cleaned.get("amount_max")
        if lo and hi and lo > hi:
            self.add_error("amount_max", "Maximum amount cannot be less than the minimum.")
        return cleaned


# ---------------------------------------------------------------------------
# Funding applications
# ---------------------------------------------------------------------------

class FundingApplicationStartForm(forms.Form):
    """Picks the business that will own this funding application."""

    business = forms.ModelChoiceField(
        queryset=None,
        widget=forms.Select(attrs=_s2_single(placeholder="Pick a verified business")),
    )

    def __init__(self, *args, entrepreneur=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["business"].queryset = Business.objects.filter(
            entrepreneur=entrepreneur,
            verification_status=Business.Status.VERIFIED,
        ).order_by("name")


class FundingApplicationForm(forms.ModelForm):
    """Application wizard form. Used in DRAFT + RETURNED_FOR_INFO states."""

    class Meta:
        model = FundingApplication
        fields = [
            "funding_request_amount",
            "pitch_summary",
            "use_of_funds",
            "traction",
            "team_summary",
            "business_plan_file",
            "financial_projections_file",
        ]
        widgets = {
            "funding_request_amount": forms.NumberInput(
                attrs={"class": INPUT_BASE, "step": "0.01", "min": "0", "placeholder": "e.g. 50000"},
            ),
            "pitch_summary": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 4}),
            "use_of_funds": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 4}),
            "traction": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 4}),
            "team_summary": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 4}),
        }
        help_texts = {
            "funding_request_amount": "Enter the amount in USD, whole numbers (e.g. 50000, not 50).",
        }


class FundingApplicationDocumentForm(forms.ModelForm):
    class Meta:
        model = FundingApplicationDocument
        fields = ["label", "file"]
        widgets = {
            "label": forms.TextInput(attrs={"class": INPUT_BASE, "placeholder": "Document label"}),
        }


FundingApplicationDocumentFormSet = inlineformset_factory(
    FundingApplication,
    FundingApplicationDocument,
    form=FundingApplicationDocumentForm,
    extra=2,
    max_num=10,
    can_delete=True,
)


class FundingApplicationDecisionForm(forms.Form):
    ACTION_CHOICES = (
        ("accept", "Accept"),
        ("reject", "Reject"),
        ("return_for_info", "Return for more info"),
    )
    action = forms.ChoiceField(
        choices=ACTION_CHOICES,
        widget=forms.Select(attrs=_s2_single(placeholder="Decision")),
    )
    note = forms.CharField(
        required=False,
        widget=forms.Textarea(
            attrs={
                "class": TEXTAREA_BASE,
                "rows": 3,
                "placeholder": "Decision note / message to applicant",
            },
        ),
    )


# ---------------------------------------------------------------------------
# Investor pitch flow
# ---------------------------------------------------------------------------

class InvestorConnectionRequestForm(forms.ModelForm):
    business = forms.ModelChoiceField(
        queryset=None,
        widget=forms.Select(attrs=_s2_single(placeholder="Pick a verified business")),
    )

    class Meta:
        model = InvestorConnectionRequest
        fields = ["business", "funding_ask", "supporting_link", "message"]
        widgets = {
            "message": forms.Textarea(
                attrs={
                    "class": TEXTAREA_BASE + " js-quill",
                    "rows": 8,
                    "placeholder": (
                        "Lead with the problem and your traction. Include the "
                        "ask, use of funds, and what you need from this investor."
                    ),
                    "data-quill-toolbar": "full",
                },
            ),
            "funding_ask": forms.NumberInput(
                attrs={
                    "class": INPUT_BASE,
                    "step": "0.01",
                    "min": "0",
                    "placeholder": "e.g. 50000",
                },
            ),
            "supporting_link": forms.URLInput(
                attrs={
                    "class": INPUT_BASE,
                    "placeholder": "https://… (deck, demo, one-pager)",
                },
            ),
        }

    def __init__(self, *args, entrepreneur=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["business"].queryset = Business.objects.filter(
            entrepreneur=entrepreneur,
            verification_status=Business.Status.VERIFIED,
        ).order_by("name")
        self.fields["funding_ask"].required = False
        self.fields["supporting_link"].required = False


class InvestorRequestDeclineForm(forms.Form):
    reason = forms.CharField(
        required=False,
        widget=forms.Textarea(
            attrs={"class": TEXTAREA_BASE, "rows": 3, "placeholder": "Optional reason for declining"},
        ),
    )


# ---------------------------------------------------------------------------
# Manual funding records  (admin only)
# ---------------------------------------------------------------------------

class ManualFundingRecordForm(forms.ModelForm):
    class Meta:
        model = ManualFundingRecord
        fields = [
            "entrepreneur",
            "business",
            "investor",
            "funder_name",
            "amount",
            "currency",
            "funded_at",
            "source_note",
        ]
        widgets = {
            "entrepreneur": forms.Select(
                attrs=_s2_single(placeholder="Pick an entrepreneur"),
            ),
            "business": forms.Select(
                attrs=_s2_single(placeholder="Pick the business"),
            ),
            "investor": forms.Select(
                attrs=_s2_single(placeholder="Optional: linked investor"),
            ),
            "funder_name": forms.TextInput(attrs={"class": INPUT_BASE}),
            "amount": forms.NumberInput(attrs={"class": INPUT_BASE, "step": "0.01", "min": "0"}),
            "currency": forms.TextInput(attrs={"class": INPUT_BASE}),
            "funded_at": forms.DateInput(
                attrs={"class": INPUT_BASE, "type": "date"},
            ),
            "source_note": forms.Textarea(attrs={"class": TEXTAREA_BASE, "rows": 3}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        from apps.smehub.onboarding.models import EntrepreneurProfile

        self.fields["entrepreneur"].queryset = EntrepreneurProfile.objects.filter(
            verification_status=EntrepreneurProfile.Status.VERIFIED,
        ).select_related("user")
        self.fields["business"].queryset = Business.objects.filter(
            verification_status=Business.Status.VERIFIED,
        ).select_related("entrepreneur__user")
        self.fields["investor"].queryset = Investor.objects.filter(
            verification_status=Investor.Status.VERIFIED,
        ).order_by("org_name")
        self.fields["investor"].required = False

    def clean(self):
        cleaned = super().clean()
        amount = cleaned.get("amount")
        if amount is not None and Decimal(amount) <= 0:
            self.add_error("amount", "Amount must be positive.")
        ent = cleaned.get("entrepreneur")
        biz = cleaned.get("business")
        if ent and biz and biz.entrepreneur_id != ent.pk:
            self.add_error("business", "Selected business does not belong to this entrepreneur.")
        return cleaned


# ---------------------------------------------------------------------------
# Dashboard share
# ---------------------------------------------------------------------------

class ShareDashboardForm(forms.Form):
    investor = forms.ModelChoiceField(
        queryset=None,
        widget=forms.Select(attrs=_s2_single(placeholder="Investor to share with")),
    )
    scope = forms.ChoiceField(
        choices=(
            ("summary", "Summary view"),
            ("full", "Full performance view"),
        ),
        widget=forms.Select(attrs=_s2_single(placeholder="Visibility scope")),
    )
    note = forms.CharField(
        required=False,
        widget=forms.TextInput(
            attrs={"class": INPUT_BASE, "placeholder": "Optional note for the audit log"},
        ),
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["investor"].queryset = Investor.objects.filter(
            verification_status=Investor.Status.VERIFIED,
        ).order_by("org_name")
