"""Premium request form.

Server-side validation for a student's manual premium activation request. Plan
and payment-method choices are sourced from :mod:`app.premium.services` so the
form and the workflow never drift apart.
"""

from __future__ import annotations

from flask_wtf import FlaskForm
from flask_wtf.file import FileAllowed, FileField
from wtforms import SelectField, StringField, SubmitField, TextAreaField
from wtforms.validators import DataRequired, Length, Optional, ValidationError


class PremiumRequestForm(FlaskForm):
    """Submit a request to be activated as a premium member.

    ``plan_name`` and ``payment_method`` choices are populated per-request from
    the admin-configured plans / enabled payment methods (see the route), so the
    form never hardcodes them.
    """

    plan_name = SelectField(
        "Plan",
        choices=[],
        validators=[DataRequired(message="Choose a plan.")],
    )
    payment_method = SelectField(
        "Payment method",
        choices=[],
        validators=[DataRequired(message="Choose how you paid.")],
    )
    # No ``Optional()`` here: it raises StopValidation on empty input, which
    # would skip the conditional-required check below. Emptiness is allowed for
    # cash and enforced for other methods by ``validate_transaction_reference``.
    transaction_reference = StringField(
        "Transaction reference",
        validators=[Length(max=120)],
    )
    receipt = FileField(
        "Receipt screenshot (optional)",
        validators=[
            Optional(),
            FileAllowed(["png", "jpg", "jpeg", "gif", "webp"], "Upload an image file."),
        ],
    )
    remarks = TextAreaField(
        "Additional notes (optional)",
        validators=[Optional(), Length(max=500)],
    )
    submit = SubmitField("Submit request")

    def validate_transaction_reference(self, field) -> None:
        """Require a reference for every method except cash."""
        if self.payment_method.data != "cash" and not (field.data or "").strip():
            raise ValidationError(
                "Enter the transaction reference for your payment."
            )
