"""
api/routes/snitch.py - API endpoints for snitch system
"""

import flask
import jwt
import os
from datetime import datetime
import core.postgres as postgres
import core.snitch as snitch_core

JWT_SECRET = os.getenv("JWT_SECRET")


def _get_user_uuid(request):
    """Extract and validate user UUID from JWT token."""
    auth_header = request.headers.get("Authorization", "")
    if not auth_header.startswith("Bearer "):
        return None

    token = auth_header[7:]
    try:
        payload = jwt.decode(token, JWT_SECRET, algorithms=["HS256"])
        return payload.get("sub")
    except jwt.ExpiredSignatureError:
        return None
    except jwt.InvalidTokenError:
        return None


def register(app):
    @app.route("/api/snitch/settings", methods=["GET"])
    def get_snitch_settings():
        """Get user's snitch settings."""
        user_uuid = _get_user_uuid(flask.request)
        if not user_uuid:
            return flask.jsonify({"error": "Unauthorized"}), 401

        settings = snitch_core.get_snitch_settings(user_uuid)

        if not settings:
            # Return defaults
            return flask.jsonify(
                {
                    "snitch_enabled": False,
                    "trigger_after_nags": 4,
                    "trigger_after_missed_doses": 1,
                    "max_snitches_per_day": 2,
                    "require_consent": True,
                    "consent_given": False,
                    "snitch_cooldown_hours": 4,
                }
            ), 200

        return flask.jsonify(
            {
                "snitch_enabled": settings.get("snitch_enabled", False),
                "trigger_after_nags": settings.get("trigger_after_nags", 4),
                "trigger_after_missed_doses": settings.get(
                    "trigger_after_missed_doses", 1
                ),
                "max_snitches_per_day": settings.get("max_snitches_per_day", 2),
                "require_consent": settings.get("require_consent", True),
                "consent_given": settings.get("consent_given", False),
                "snitch_cooldown_hours": settings.get("snitch_cooldown_hours", 4),
            }
        ), 200

    @app.route("/api/snitch/settings", methods=["PUT"])
    def update_snitch_settings():
        """Update user's snitch settings."""
        user_uuid = _get_user_uuid(flask.request)
        if not user_uuid:
            return flask.jsonify({"error": "Unauthorized"}), 401

        data = flask.request.get_json()
        if not data:
            return flask.jsonify({"error": "No data provided"}), 400

        # Build update data
        update_data = {
            "snitch_enabled": data.get("snitch_enabled", False),
            "trigger_after_nags": data.get("trigger_after_nags", 4),
            "trigger_after_missed_doses": data.get("trigger_after_missed_doses", 1),
            "max_snitches_per_day": data.get("max_snitches_per_day", 2),
            "require_consent": data.get("require_consent", True),
            "consent_given": data.get("consent_given", False),
            "snitch_cooldown_hours": data.get("snitch_cooldown_hours", 4),
            "updated_at": datetime.utcnow(),
        }

        # Check if settings exist
        existing = snitch_core.get_snitch_settings(user_uuid)

        if existing:
            postgres.update("snitch_settings", update_data, {"user_uuid": user_uuid})
        else:
            update_data["user_uuid"] = user_uuid
            update_data["created_at"] = datetime.utcnow()
            postgres.insert("snitch_settings", update_data)

        return flask.jsonify({"success": True}), 200

    @app.route("/api/snitch/consent", methods=["POST"])
    def give_consent():
        """Give or revoke consent for snitching."""
        user_uuid = _get_user_uuid(flask.request)
        if not user_uuid:
            return flask.jsonify({"error": "Unauthorized"}), 401

        data = flask.request.get_json()
        consent_given = data.get("consent_given", False)

        snitch_core.update_consent(user_uuid, consent_given)

        return flask.jsonify({"success": True, "consent_given": consent_given}), 200

    @app.route("/api/snitch/contacts", methods=["GET"])
    def get_snitch_contacts():
        """Get user's snitch contacts."""
        user_uuid = _get_user_uuid(flask.request)
        if not user_uuid:
            return flask.jsonify({"error": "Unauthorized"}), 401

        contacts = snitch_core.get_snitch_contacts(user_uuid, active_only=False)

        return flask.jsonify(
            [
                {
                    "id": c.get("id"),
                    "contact_name": c.get("contact_name"),
                    "contact_type": c.get("contact_type"),
                    "contact_value": c.get("contact_value"),
                    "priority": c.get("priority", 1),
                    "notify_all": c.get("notify_all", False),
                    "is_active": c.get("is_active", True),
                }
                for c in contacts
            ]
        ), 200

    @app.route("/api/snitch/contacts", methods=["POST"])
    def add_snitch_contact():
        """Add a new snitch contact."""
        user_uuid = _get_user_uuid(flask.request)
        if not user_uuid:
            return flask.jsonify({"error": "Unauthorized"}), 401

        data = flask.request.get_json()

        # Validate required fields
        required = ["contact_name", "contact_type", "contact_value"]
        for field in required:
            if not data.get(field):
                return flask.jsonify({"error": f"Missing required field: {field}"}), 400

        # Validate contact_type
        if data["contact_type"] not in ["discord", "email", "sms"]:
            return flask.jsonify(
                {"error": "contact_type must be discord, email, or sms"}
            ), 400

        contact_data = {
            "user_uuid": user_uuid,
            "contact_name": data["contact_name"],
            "contact_type": data["contact_type"],
            "contact_value": data["contact_value"],
            "priority": data.get("priority", 1),
            "notify_all": data.get("notify_all", False),
            "is_active": data.get("is_active", True),
            "created_at": datetime.utcnow(),
        }

        result = postgres.insert("snitch_contacts", contact_data)

        return flask.jsonify(
            {"success": True, "contact_id": result.get("id") if result else None}
        ), 201

    @app.route("/api/snitch/contacts/<contact_id>", methods=["PUT"])
    def update_snitch_contact(contact_id):
        """Update a snitch contact."""
        user_uuid = _get_user_uuid(flask.request)
        if not user_uuid:
            return flask.jsonify({"error": "Unauthorized"}), 401

        data = flask.request.get_json()

        # Check contact exists and belongs to user
        contacts = postgres.select(
            "snitch_contacts", {"id": contact_id, "user_uuid": user_uuid}
        )
        if not contacts:
            return flask.jsonify({"error": "Contact not found"}), 404

        update_data = {}
        if "contact_name" in data:
            update_data["contact_name"] = data["contact_name"]
        if "contact_type" in data:
            if data["contact_type"] not in ["discord", "email", "sms"]:
                return flask.jsonify({"error": "Invalid contact_type"}), 400
            update_data["contact_type"] = data["contact_type"]
        if "contact_value" in data:
            update_data["contact_value"] = data["contact_value"]
        if "priority" in data:
            update_data["priority"] = data["priority"]
        if "notify_all" in data:
            update_data["notify_all"] = data["notify_all"]
        if "is_active" in data:
            update_data["is_active"] = data["is_active"]

        if update_data:
            postgres.update("snitch_contacts", update_data, {"id": contact_id})

        return flask.jsonify({"success": True}), 200

    @app.route("/api/snitch/contacts/<contact_id>", methods=["DELETE"])
    def delete_snitch_contact(contact_id):
        """Delete a snitch contact."""
        user_uuid = _get_user_uuid(flask.request)
        if not user_uuid:
            return flask.jsonify({"error": "Unauthorized"}), 401

        # Check contact exists and belongs to user
        contacts = postgres.select(
            "snitch_contacts", {"id": contact_id, "user_uuid": user_uuid}
        )
        if not contacts:
            return flask.jsonify({"error": "Contact not found"}), 404

        postgres.delete("snitch_contacts", {"id": contact_id})

        return flask.jsonify({"success": True}), 200

    @app.route("/api/snitch/history", methods=["GET"])
    def get_snitch_history():
        """Get user's snitch history."""
        user_uuid = _get_user_uuid(flask.request)
        if not user_uuid:
            return flask.jsonify({"error": "Unauthorized"}), 401

        days = flask.request.args.get("days", 7, type=int)
        history = snitch_core.get_snitch_history(user_uuid, days)

        return flask.jsonify(
            [
                {
                    "id": h.get("id"),
                    "contact_id": h.get("contact_id"),
                    "medication_id": h.get("medication_id"),
                    "trigger_reason": h.get("trigger_reason"),
                    "snitch_count_today": h.get("snitch_count_today"),
                    "sent_at": h.get("sent_at").isoformat()
                    if h.get("sent_at")
                    else None,
                    "delivered": h.get("delivered"),
                }
                for h in history
            ]
        ), 200

    @app.route("/api/snitch/test", methods=["POST"])
    def test_snitch():
        """Test snitch functionality (sends to first contact only)."""
        user_uuid = _get_user_uuid(flask.request)
        if not user_uuid:
            return flask.jsonify({"error": "Unauthorized"}), 401

        # Get first active contact
        contacts = snitch_core.get_snitch_contacts(user_uuid, active_only=True)
        if not contacts:
            return flask.jsonify({"error": "No active contacts configured"}), 400

        # Send test message
        contact = contacts[0]
        test_message = f"🧪 This is a test snitch notification for {contact.get('contact_name')}. If you're receiving this, the snitch system is working!"

        # Insert into snitch_log so the bot will pick it up and send it
        log_data = {
            "user_uuid": user_uuid,
            "contact_id": contact.get("id"),
            "medication_id": None,  # Test snitch, no actual medication
            "trigger_reason": "test",
            "snitch_count_today": 1,
            "message_content": test_message,
            "sent_at": datetime.utcnow(),
            "delivered": False,  # Bot will pick this up and send it
        }
        postgres.insert("snitch_log", log_data)

        return flask.jsonify(
            {
                "success": True,
                "message": f"✅ Test snitch sent to {contact.get('contact_name')}! Check their Discord DMs in the next 30 seconds.",
            }
        ), 200
