"""A7: Conversation dynamics — turns, ratios, timing, gaps."""

from datetime import datetime

from .base import BaseAnalyzer


def _parse_ts(ts) -> datetime | None:
    if not ts:
        return None
    try:
        return datetime.fromisoformat(str(ts).replace("Z", "+00:00"))
    except (ValueError, TypeError):
        return None


class ConversationDynamicsAnalyzer(BaseAnalyzer):
    name = "a07_conversation_dynamics"

    def analyze(self, sessions_df, messages_df, tool_calls_df, tool_results_df, token_usage_df) -> dict:
        per_session = []

        for session in self.iter_sessions(sessions_df):
            sid = session["id"]
            msgs = self.get_session_messages(messages_df, sid)
            if msgs.empty:
                continue

            user_char_total = 0
            assistant_char_total = 0
            user_count = 0
            ai_between_users = []
            current_ai_count = 0
            user_timestamps = []

            for _, m in msgs.iterrows():
                mt = m["msg_type"]
                if mt == "user":
                    user_count += 1
                    if current_ai_count > 0 or user_count > 1:
                        ai_between_users.append(current_ai_count)
                    current_ai_count = 0
                    uc = m.get("content")
                    user_char_total += len(uc) if isinstance(uc, str) else 0
                    ts = _parse_ts(m.get("timestamp"))
                    if ts:
                        user_timestamps.append(ts)
                elif mt in ("assistant", "tool_call"):
                    current_ai_count += 1
                    if mt == "assistant":
                        c = m.get("content")
                        assistant_char_total += len(c) if isinstance(c, str) else 0

            if current_ai_count > 0:
                ai_between_users.append(current_ai_count)

            ai_plus_tc = sum(1 for _, m in msgs.iterrows() if m["msg_type"] in ("assistant", "tool_call"))
            avg_ai_per_turn = ai_plus_tc / max(user_count, 1)
            deepest_turn = max(ai_between_users) if ai_between_users else 0
            user_ai_ratio = user_char_total / max(assistant_char_total, 1)

            # All message timestamps for gap computation
            all_timestamps = [_parse_ts(m.get("timestamp")) for _, m in msgs.iterrows()]
            all_timestamps = [t for t in all_timestamps if t]

            # Wall-clock duration (first to last message)
            wall_duration_min = None
            if len(all_timestamps) >= 2:
                wall_duration_min = round((all_timestamps[-1] - all_timestamps[0]).total_seconds() / 60, 2)

            # Active duration: sum of consecutive gaps ≤ 5 min (300s)
            # Gaps > 5 min are idle time (user walked away)
            IDLE_THRESHOLD_SEC = 300
            active_secs = 0.0
            for i in range(1, len(all_timestamps)):
                gap = (all_timestamps[i] - all_timestamps[i - 1]).total_seconds()
                if gap <= IDLE_THRESHOLD_SEC:
                    active_secs += gap
                else:
                    # Count a small overhead for resuming (30s)
                    active_secs += 30
            active_duration_min = round(active_secs / 60, 2) if len(all_timestamps) >= 2 else None

            user_gaps = []
            for i in range(1, len(user_timestamps)):
                user_gaps.append((user_timestamps[i] - user_timestamps[i - 1]).total_seconds())

            session_start = all_timestamps[0].isoformat() if all_timestamps else None

            per_session.append({
                "session_id": sid,
                "session_start": session_start,
                "total_turns": user_count,
                "avg_ai_msgs_per_turn": round(avg_ai_per_turn, 2),
                "deepest_turn": deepest_turn,
                "user_to_ai_char_ratio": round(user_ai_ratio, 3),
                "session_duration_min": active_duration_min,
                "wall_duration_min": wall_duration_min,
                "avg_gap_between_user_msgs_sec": round(sum(user_gaps) / len(user_gaps), 2) if user_gaps else None,
                "longest_gap_sec": round(max(user_gaps), 2) if user_gaps else None,
            })

        return {"total_sessions": len(per_session), "per_session": per_session}
