"""Trigger settings for auto-start detection."""

import json
from collections.abc import Sequence
from typing import Annotated, cast

from pydantic import Field, field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict

from noteflow.config.settings._base import ENV_FILE, EXTRA_IGNORE


def _string_list_from_unknown(value: object) -> list[str]:
    if value is None:
        return []
    if isinstance(value, str):
        stripped = value.strip()
        if not stripped:
            return []
        if stripped.startswith("[") and stripped.endswith("]"):
            try:
                parsed = json.loads(stripped)
            except json.JSONDecodeError:
                parsed = None
            if isinstance(parsed, list):
                parsed_items = cast(list[object], parsed)
                return [
                    str(item).strip()
                    for item in parsed_items
                    if str(item).strip()
                ]
        return [item.strip() for item in value.split(",") if item.strip()]
    if isinstance(value, (list, tuple)):
        items = cast(Sequence[object], value)
        return [str(item) for item in items]
    return []


def _dict_list_from_unknown(value: object) -> list[dict[str, object]]:
    if value is None:
        return []
    if isinstance(value, str):
        stripped = value.strip()
        if not stripped:
            return []
        try:
            parsed = json.loads(stripped)
        except json.JSONDecodeError:
            return []
        return _dict_list_from_unknown(parsed)
    if isinstance(value, dict):
        raw = cast(dict[object, object], value)
        normalized: dict[str, object] = {str(key): val for key, val in raw.items()}
        return [normalized]
    if isinstance(value, list):
        items = cast(Sequence[object], value)
        result: list[dict[str, object]] = []
        for item in items:
            if isinstance(item, dict):
                raw_item = cast(dict[object, object], item)
                result.append({str(key): val for key, val in raw_item.items()})
        return result
    return []


class TriggerSettings(BaseSettings):
    """Client trigger settings loaded from environment variables."""

    model_config = SettingsConfigDict(
        env_prefix="NOTEFLOW_",
        env_file=ENV_FILE,
        env_file_encoding="utf-8",
        enable_decoding=False,
        extra=EXTRA_IGNORE,
    )

    # Trigger settings (client-side)
    trigger_enabled: Annotated[
        bool,
        Field(default=False, description="Enable smart recording triggers (opt-in)"),
    ]
    trigger_auto_start: Annotated[
        bool,
        Field(default=False, description="Auto-start recording on high confidence"),
    ]
    trigger_rate_limit_minutes: Annotated[
        int,
        Field(default=10, ge=1, le=60, description="Minimum minutes between trigger prompts"),
    ]
    trigger_snooze_minutes: Annotated[
        int,
        Field(default=30, ge=5, le=480, description="Default snooze duration in minutes"),
    ]
    trigger_poll_interval_seconds: Annotated[
        float,
        Field(default=2.0, ge=0.5, le=30.0, description="Trigger polling interval in seconds"),
    ]
    trigger_confidence_ignore: Annotated[
        float,
        Field(default=0.40, ge=0.0, le=1.0, description="Confidence below which to ignore"),
    ]
    trigger_confidence_auto: Annotated[
        float,
        Field(default=0.80, ge=0.0, le=1.0, description="Confidence to auto-start recording"),
    ]

    # App audio trigger tuning (system output from whitelisted apps)
    trigger_audio_enabled: Annotated[
        bool,
        Field(default=True, description="Enable app audio activity detection"),
    ]
    trigger_audio_threshold_db: Annotated[
        float,
        Field(default=-40.0, ge=-60.0, le=0.0, description="Audio activity threshold in dB"),
    ]
    trigger_audio_window_seconds: Annotated[
        float,
        Field(default=5.0, ge=1.0, le=30.0, description="Audio activity window in seconds"),
    ]
    trigger_audio_min_active_ratio: Annotated[
        float,
        Field(default=0.6, ge=0.0, le=1.0, description="Minimum active ratio in window"),
    ]
    trigger_audio_min_samples: Annotated[
        int,
        Field(default=10, ge=1, le=200, description="Minimum samples before evaluating audio"),
    ]
    trigger_audio_max_history: Annotated[
        int,
        Field(default=50, ge=10, le=1000, description="Max audio activity samples to retain"),
    ]

    # Calendar trigger tuning (optional integration)
    trigger_calendar_enabled: Annotated[
        bool,
        Field(default=False, description="Enable calendar-based trigger detection"),
    ]
    trigger_calendar_lookahead_minutes: Annotated[
        int,
        Field(default=5, ge=0, le=60, description="Minutes before event start to trigger"),
    ]
    trigger_calendar_lookbehind_minutes: Annotated[
        int,
        Field(default=5, ge=0, le=60, description="Minutes after event start to keep triggering"),
    ]
    trigger_calendar_events: Annotated[
        list[dict[str, object]],
        Field(
            default_factory=list,
            description="Calendar events as JSON list of {start, end, title}",
        ),
    ]

    # Foreground app trigger tuning
    trigger_foreground_enabled: Annotated[
        bool,
        Field(default=True, description="Enable foreground app detection"),
    ]
    trigger_meeting_apps: Annotated[
        list[str],
        Field(
            default_factory=lambda: [
                "zoom",
                "teams",
                "microsoft teams",
                "meet",
                "google meet",
                "slack",
                "webex",
                "discord",
                "skype",
                "gotomeeting",
                "facetime",
                "webinar",
                "ringcentral",
            ],
            description="Meeting app name substrings to detect",
        ),
    ]
    trigger_suppressed_apps: Annotated[
        list[str],
        Field(default_factory=list, description="Meeting app substrings to ignore"),
    ]

    # Signal weights
    trigger_weight_audio: Annotated[
        float,
        Field(default=0.30, ge=0.0, le=1.0, description="Audio signal confidence weight"),
    ]
    trigger_weight_foreground: Annotated[
        float,
        Field(
            default=0.40,
            ge=0.0,
            le=1.0,
            description="Foreground app signal confidence weight",
        ),
    ]
    trigger_weight_calendar: Annotated[
        float,
        Field(default=0.30, ge=0.0, le=1.0, description="Calendar signal confidence weight"),
    ]

    @field_validator("trigger_meeting_apps", "trigger_suppressed_apps", mode="before")
    @classmethod
    def _parse_csv_list(cls, value: object) -> list[str]:
        return _string_list_from_unknown(value)

    @field_validator("trigger_calendar_events", mode="before")
    @classmethod
    def _parse_calendar_events(cls, value: object) -> list[dict[str, object]]:
        return _dict_list_from_unknown(value)
