from __future__ import annotations

import re
from dataclasses import dataclass
from typing import Any, Callable


@dataclass(frozen=True)
class KreaRowFields:
    subject_type: str
    primary: str
    item: str
    scene: str
    pose: str
    expression: str
    composition: str
    source_composition: str
    camera: str
    camera_scene: str
    style: str


@dataclass(frozen=True)
class KreaRowFieldDependencies:
    clean: Callable[[Any], str]
    row_value: Callable[[dict[str, Any], str, tuple[str, ...]], str]
    camera_phrase: Callable[[dict[str, Any]], str]
    camera_scene_phrase: Callable[[dict[str, Any]], str]
    style_phrase: Callable[[dict[str, Any], str], str]
    expression_disabled: Callable[[dict[str, Any]], bool]


def _without_vertical_prefix(text: str) -> str:
    return re.sub(r"^vertical\s+", "", text, flags=re.IGNORECASE)


def _clean_item_suffix(text: str) -> str:
    return re.sub(r",?\s*(fashion editorial|resort) styling$", "", text, flags=re.IGNORECASE)


def extract_krea_row_fields(
    row: dict[str, Any],
    style_mode: str,
    deps: KreaRowFieldDependencies,
) -> KreaRowFields:
    item = deps.row_value(row, "item", ("Sexual pose", "Erotic outfit", "Clothing")) or deps.clean(
        row.get("custom_item")
    )
    item = _clean_item_suffix(item)
    expression = ""
    if not deps.expression_disabled(row):
        expression = deps.row_value(row, "character_expression_text", ()) or deps.row_value(
            row,
            "expression",
            ("Facial expressions", "Facial expression"),
        )
    composition = _without_vertical_prefix(deps.row_value(row, "composition", ("Composition",)))
    source_composition = _without_vertical_prefix(deps.clean(row.get("source_composition")) or composition)
    return KreaRowFields(
        subject_type=deps.clean(row.get("subject_type")),
        primary=deps.clean(row.get("primary_subject")),
        item=item,
        scene=deps.row_value(row, "scene_text", ("Setting", "Scene")) or deps.clean(row.get("scene")),
        pose=deps.row_value(row, "pose", ("Sexual pose", "Pose")),
        expression=expression,
        composition=composition,
        source_composition=source_composition,
        camera=deps.camera_phrase(row),
        camera_scene=deps.camera_scene_phrase(row),
        style=deps.style_phrase(row, style_mode),
    )
