"""
Absfuyu: Google form
--------------------
Google form - Question Model

Version: 6.8.0
Date updated: 26/04/2026 (dd/mm/yyyy)
"""

# Module level
# ---------------------------------------------------------------------------
__all__ = ["Question"]

# Library
# ---------------------------------------------------------------------------
from dataclasses import dataclass, field
from enum import Enum
from typing import Any, NotRequired, TypedDict


# Enum
# ---------------------------------------------------------------------------
class QuestionType(Enum):
    SHORT_ANSWER = 0
    PARAGRAPH = 1
    MULTIPLE_CHOICE = 2
    DROPDOWN = 3
    CHECKBOXES = 4
    LINEAR_SCALE = 5
    GRID = 7
    SECTION = 8
    DATE = 9
    TIME = 10
    RATE = 18
    UNKNOWN = -1

    @classmethod
    def from_code(cls, code: int):
        if code in cls._value2member_map_:
            return cls(code)

        return cls.UNKNOWN


class ValidationType(Enum):
    NUMBER = 1
    TEXT = 2
    REGEX = 4
    LENGTH = 6
    SELECT = 7
    COLUMN = 8

    UNKNOWN = -1

    @classmethod
    def from_code(cls, code: int):
        if code in cls._value2member_map_:
            return cls(code)

        return cls.UNKNOWN


class ValidationSubtype(Enum):
    BIGGER = 1
    BIGGER_OR_EQUAL = 2
    SMALLER = 3
    SMALLER_OR_EQUAL = 4
    EQUAL = 5
    NOT_EQUAL = 6
    BETWEEN = 7
    NOT_BETWEEN = 8
    IS_NUMBER = 9
    IS_INT = 10

    CONTAIN = 100
    NOT_CONTAIN = 101
    IS_EMAIL = 102
    IS_URL = 103

    AT_LEAST = 200
    AT_MOST = 201
    EXACTLY = 204

    MAXIMUM_CHAR_LENGTH = 202
    MINIMUM_CHAR_LENGTH = 203

    CONTAIN_WORD = 299
    NOT_CONTAIN_WORD = 300
    MATCH = 301
    NOT_MATCH = 302

    ONE_EACH = 205  # One answer each column (grid)

    UNKNOWN = -1

    @classmethod
    def from_code(cls, code: int):
        if code in cls._value2member_map_:
            return cls(code)

        return cls.UNKNOWN


# Schema - Unused
# ---------------------------------------------------------------------------
class OptionSchema(TypedDict):
    text: str
    raw: list[Any]


class ValidationRule(TypedDict):
    type: int
    subtype: int
    args: list[str]
    message: str


class AnswerSchema(TypedDict):
    entry_id: int
    required: bool
    options: list[OptionSchema]
    validation: NotRequired[list[ValidationRule]]
    raw: list[Any]


class QuestionSchema(TypedDict):
    question_id: int
    text: str
    description: str | None
    type_code: int
    answers: list[AnswerSchema]
    raw: list[Any]


# Dataclass
# ---------------------------------------------------------------------------
@dataclass
class Validation:
    type: ValidationType = ValidationType.UNKNOWN
    subtype: ValidationSubtype = ValidationSubtype.UNKNOWN
    args: list[str] = field(default_factory=list)
    message: str = ""


@dataclass
class Option:
    text: str
    raw: list[Any] = field(default_factory=[], repr=False)


@dataclass
class Answer:
    entry_id: str
    required: bool
    options: list[Option] = field(default_factory=list)
    validation: list[Validation] = field(default_factory=list)
    extra: dict[str, Any] = field(default_factory=dict)
    raw: list[Any] = field(default_factory=list, repr=False)


@dataclass
class Question:
    question_id: int
    text: str
    description: str | None
    type: QuestionType
    answers: list[Answer]

    required: bool = False
    entry_ids: list[str] = field(default_factory=list)

    branching: dict[str, int | None] = field(default_factory=dict)
    page_index: int = 0

    # Raw
    raw: list[Any] = field(default_factory=list, repr=False)

    def __post_init__(self) -> None:
        if self.type == QuestionType.LINEAR_SCALE:
            # Update text
            try:
                ans = self.answers
                desc = ans[0].raw[3]
                self.answers[0].extra["left_text"] = desc[0]
                self.answers[0].extra["right_text"] = desc[1]
            except Exception:
                pass

        elif self.type == QuestionType.GRID:
            # Update text, validation, type
            try:
                validation = self.raw[8]
                for i, answer in enumerate(self.answers):
                    text = answer.raw[3][0]

                    self.answers[i].extra["text"] = text

                    try:
                        is_checkbox = bool(int(answer.raw[-1][0]))
                        self.answers[i].extra["is_checkbox"] = is_checkbox
                    except Exception:
                        pass

                    if validation is not None:
                        self.answers[i].validation.append(
                            Validation(
                                type=ValidationType.from_code(int(validation[0][0])),
                                subtype=ValidationSubtype.from_code(int(validation[0][1])),
                            )
                        )
            except Exception:
                pass

        elif self.type == QuestionType.DATE:
            # Update extra
            for i, answer in enumerate(self.answers):
                try:
                    param = answer.raw[-1]
                    include_time = bool(int(param[0]))
                    include_year = bool(int(param[1]))
                    self.answers[i].extra["include_time"] = include_time
                    self.answers[i].extra["include_year"] = include_year
                except Exception:
                    pass

        elif self.type == QuestionType.TIME:
            # Update extra
            for i, answer in enumerate(self.answers):
                try:
                    is_duration = bool(int(answer.raw[-1][0]))
                    self.answers[i].extra["is_duration"] = is_duration
                except Exception:
                    pass
