#!/usr/bin/env python3
"""
Survey CRUD module for user feedback surveys.

Manages surveys, invitations, and responses.
Uses get_connection() from database.py.
"""

import json
from pathlib import Path
from typing import Optional, Dict, List, Any

from database import get_connection, get_db_path


# =============================================================================
# Default Survey Questions
# =============================================================================

DEFAULT_QUESTIONS = [
    {
        "key": "video_quality",
        "type": "rating",
        "text": "Как вы оцениваете качество сгенерированных видео?",
        "min": 1,
        "max": 5,
    },
    {
        "key": "video_usage",
        "type": "single",
        "text": "Использовали ли вы видео в карточках товаров на маркетплейсе?",
        "options": [
            "Да, загрузил(а) в карточку",
            "Нет, качество не устроило",
            "Нет, были артефакты (странные руки, лица и т.д.)",
            "Нет, не знаю как загрузить на маркетплейс",
            "Нет, не успел(а)",
        ],
    },
    {
        "key": "stop_reason",
        "type": "multi",
        "text": "Что помешало продолжить использование? (можно выбрать несколько)",
        "options": [
            "Хотел(а) купить, но цена высокая",
            "Качество видео не устроило",
            "Были артефакты в видео",
            "Видео не подходит для моего товара",
            "Сложно разобраться в боте",
            "Долго ждать генерацию",
            "Не увидел(а) результат в продажах",
            "Забыл(а) / не было времени",
        ],
    },
    {
        "key": "fair_price",
        "type": "single",
        "text": "Какая цена за одну генерацию видео кажется вам справедливой?",
        "options": [
            "Только бесплатно",
            "До 100 ₽",
            "100–300 ₽",
            "300–500 ₽",
            "Более 500 ₽",
        ],
    },
    {
        "key": "voice_messages",
        "type": "single",
        "text": "Знали ли вы, что можно отправлять голосовые сообщения для описания правок к видео?",
        "options": [
            "Да, пользовался(ась) — удобно",
            "Да, пользовался(ась) — неудобно",
            "Знал(а), но не пробовал(а)",
            "Нет, не знал(а)",
        ],
    },
    {
        "key": "nps",
        "type": "nps",
        "text": "Насколько вероятно, что вы порекомендуете наш сервис коллегам?",
        "label": "0 — точно нет, 10 — обязательно",
        "min": 0,
        "max": 10,
    },
    {
        "key": "improvement",
        "type": "text",
        "text": "Что бы вы хотели улучшить в сервисе? (необязательно)",
        "optional": True,
    },
]


# =============================================================================
# Survey CRUD
# =============================================================================

def create_survey(
    title: str,
    questions_json: Optional[str] = None,
    reward_tokens: int = 3,
    reward_days: int = 7,
    created_by: Optional[int] = None,
    db_path: Optional[Path] = None,
) -> int:
    """Create a new survey. Returns survey ID."""
    if questions_json is None:
        questions_json = json.dumps(DEFAULT_QUESTIONS, ensure_ascii=False)
    with get_connection(db_path) as conn:
        cursor = conn.cursor()
        cursor.execute("""
            INSERT INTO surveys (title, questions_json, reward_tokens, reward_days, created_by)
            VALUES (?, ?, ?, ?, ?)
        """, (title, questions_json, reward_tokens, reward_days, created_by))
        return cursor.lastrowid


def get_survey(survey_id: int, db_path: Optional[Path] = None) -> Optional[Dict[str, Any]]:
    """Get survey by ID."""
    with get_connection(db_path) as conn:
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM surveys WHERE id = ?", (survey_id,))
        row = cursor.fetchone()
        return dict(row) if row else None


def get_active_surveys(db_path: Optional[Path] = None) -> List[Dict[str, Any]]:
    """Get all active surveys."""
    with get_connection(db_path) as conn:
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM surveys WHERE is_active = 1 ORDER BY id DESC")
        return [dict(row) for row in cursor.fetchall()]


def deactivate_survey(survey_id: int, db_path: Optional[Path] = None) -> bool:
    """Deactivate a survey."""
    with get_connection(db_path) as conn:
        cursor = conn.cursor()
        cursor.execute("UPDATE surveys SET is_active = 0 WHERE id = ?", (survey_id,))
        return cursor.rowcount > 0


# =============================================================================
# Invitation CRUD
# =============================================================================

def create_invitation(
    survey_id: int,
    user_id: int,
    db_path: Optional[Path] = None,
) -> Optional[int]:
    """Create an invitation. Returns invitation ID, or None if duplicate."""
    with get_connection(db_path) as conn:
        cursor = conn.cursor()
        try:
            cursor.execute("""
                INSERT INTO survey_invitations (survey_id, user_id)
                VALUES (?, ?)
            """, (survey_id, user_id))
            return cursor.lastrowid
        except Exception:
            return None


def get_invitation(survey_id: int, user_id: int, db_path: Optional[Path] = None) -> Optional[Dict[str, Any]]:
    """Get invitation by survey_id + user_id."""
    with get_connection(db_path) as conn:
        cursor = conn.cursor()
        cursor.execute(
            "SELECT * FROM survey_invitations WHERE survey_id = ? AND user_id = ?",
            (survey_id, user_id),
        )
        row = cursor.fetchone()
        return dict(row) if row else None


def get_invitation_by_id(invitation_id: int, db_path: Optional[Path] = None) -> Optional[Dict[str, Any]]:
    """Get invitation by its ID."""
    with get_connection(db_path) as conn:
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM survey_invitations WHERE id = ?", (invitation_id,))
        row = cursor.fetchone()
        return dict(row) if row else None


def update_invitation_status(
    invitation_id: int,
    status: str,
    db_path: Optional[Path] = None,
) -> bool:
    """Update invitation status (sent → started → completed)."""
    ts_field = {
        "started": "started_at",
        "completed": "completed_at",
    }.get(status)
    with get_connection(db_path) as conn:
        cursor = conn.cursor()
        if ts_field:
            cursor.execute(
                f"UPDATE survey_invitations SET status = ?, {ts_field} = CURRENT_TIMESTAMP WHERE id = ?",
                (status, invitation_id),
            )
        else:
            cursor.execute(
                "UPDATE survey_invitations SET status = ? WHERE id = ?",
                (status, invitation_id),
            )
        return cursor.rowcount > 0


def mark_invitation_rewarded(invitation_id: int, db_path: Optional[Path] = None) -> bool:
    """Set rewarded=1 on an invitation."""
    with get_connection(db_path) as conn:
        cursor = conn.cursor()
        cursor.execute(
            "UPDATE survey_invitations SET rewarded = 1 WHERE id = ?",
            (invitation_id,),
        )
        return cursor.rowcount > 0


# =============================================================================
# Response CRUD
# =============================================================================

def save_response(
    invitation_id: int,
    survey_id: int,
    user_id: int,
    question_key: str,
    answer_value: str,
    db_path: Optional[Path] = None,
) -> bool:
    """Save or update a survey response."""
    with get_connection(db_path) as conn:
        cursor = conn.cursor()
        cursor.execute("""
            INSERT OR REPLACE INTO survey_responses
                (invitation_id, survey_id, user_id, question_key, answer_value)
            VALUES (?, ?, ?, ?, ?)
        """, (invitation_id, survey_id, user_id, question_key, answer_value))
        return cursor.rowcount > 0


def get_user_responses(invitation_id: int, db_path: Optional[Path] = None) -> Dict[str, str]:
    """Get all responses for an invitation as {question_key: answer_value}."""
    with get_connection(db_path) as conn:
        cursor = conn.cursor()
        cursor.execute(
            "SELECT question_key, answer_value FROM survey_responses WHERE invitation_id = ?",
            (invitation_id,),
        )
        return {row["question_key"]: row["answer_value"] for row in cursor.fetchall()}


# =============================================================================
# Target Users
# =============================================================================

def get_survey_target_users(
    limit: int = 100,
    db_path: Optional[Path] = None,
) -> List[Dict[str, Any]]:
    """Get inactive users eligible for survey (tried product, no purchases, not already invited)."""
    with get_connection(db_path) as conn:
        cursor = conn.cursor()
        cursor.execute("""
            SELECT u.* FROM users u
            WHERE (u.giveaway_received = 1 OR u.gift_pack_received = 1)
              AND u.balance = 0 AND u.total_purchased = 0 AND u.is_blocked = 0
              AND EXISTS (
                SELECT 1 FROM transactions t
                WHERE t.user_id = u.user_id AND t.type = 'generation'
              )
              AND NOT EXISTS (
                SELECT 1 FROM survey_invitations si WHERE si.user_id = u.user_id
              )
              AND NOT EXISTS (
                SELECT 1 FROM transactions t
                WHERE t.user_id = u.user_id AND t.type = 'generation'
                  AND t.created_at > datetime('now', '-2 days')
              )
            ORDER BY u.created_at DESC
            LIMIT ?
        """, (limit,))
        return [dict(row) for row in cursor.fetchall()]


# =============================================================================
# Statistics & Export
# =============================================================================

def get_survey_stats(survey_id: int, db_path: Optional[Path] = None) -> Dict[str, Any]:
    """Get aggregated survey statistics."""
    with get_connection(db_path) as conn:
        cursor = conn.cursor()

        # Invitation counts by status
        cursor.execute("""
            SELECT status, COUNT(*) as count
            FROM survey_invitations WHERE survey_id = ?
            GROUP BY status
        """, (survey_id,))
        status_counts = {row["status"]: row["count"] for row in cursor.fetchall()}

        total_sent = sum(status_counts.values())
        completed = status_counts.get("completed", 0)
        started = status_counts.get("started", 0)

        # Per-question response distributions
        cursor.execute("""
            SELECT question_key, answer_value, COUNT(*) as count
            FROM survey_responses WHERE survey_id = ?
            GROUP BY question_key, answer_value
            ORDER BY question_key, count DESC
        """, (survey_id,))

        questions = {}
        for row in cursor.fetchall():
            key = row["question_key"]
            if key not in questions:
                questions[key] = {}
            questions[key][row["answer_value"]] = row["count"]

        # NPS calculation
        nps_data = questions.get("nps", {})
        promoters = sum(v for k, v in nps_data.items() if k.isdigit() and int(k) >= 9)
        detractors = sum(v for k, v in nps_data.items() if k.isdigit() and int(k) <= 6)
        nps_total = sum(nps_data.values())
        nps_score = None
        if nps_total > 0:
            nps_score = round((promoters - detractors) / nps_total * 100)

        return {
            "total_sent": total_sent,
            "started": started,
            "completed": completed,
            "status_counts": status_counts,
            "completion_rate": round(completed / total_sent * 100, 1) if total_sent else 0,
            "questions": questions,
            "nps_score": nps_score,
            "nps_total": nps_total,
        }


def get_all_responses_export(survey_id: int, db_path: Optional[Path] = None) -> List[Dict[str, Any]]:
    """Get all responses for export, grouped by user."""
    with get_connection(db_path) as conn:
        cursor = conn.cursor()
        cursor.execute("""
            SELECT si.user_id, si.status, si.completed_at,
                   u.username, u.first_name,
                   sr.question_key, sr.answer_value
            FROM survey_invitations si
            LEFT JOIN users u ON si.user_id = u.user_id
            LEFT JOIN survey_responses sr ON sr.invitation_id = si.id
            WHERE si.survey_id = ?
            ORDER BY si.user_id, sr.id
        """, (survey_id,))

        users = {}
        for row in cursor.fetchall():
            uid = row["user_id"]
            if uid not in users:
                users[uid] = {
                    "user_id": uid,
                    "username": row["username"],
                    "first_name": row["first_name"],
                    "status": row["status"],
                    "completed_at": row["completed_at"],
                    "answers": {},
                }
            if row["question_key"]:
                users[uid]["answers"][row["question_key"]] = row["answer_value"]

        return list(users.values())
