import hmac
import hashlib
import json
from datetime import datetime
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify, current_app
from flask_login import login_required, current_user
from app.extensions import db, csrf
from app.models.features import BackgroundTask, WebhookEndpoint, ActivityLog

integrations_bp = Blueprint("integrations", __name__, url_prefix="/integrations")

SUPPORTED_PLATFORMS = [
    ("zapier", "Zapier", "https://zapier.com", "Connect with 5000+ apps via Zapier"),
    ("make", "Make (Integromat)", "https://www.make.com", "Visual automation workflows"),
    ("n8n", "n8n", "https://n8n.io", "Self-hosted workflow automation (open source)"),
]

WEBHOOK_EVENTS = [
    "report.created", "report.completed", "report.updated",
    "investor.added", "investor.stage_changed",
    "campaign.created", "campaign.published",
    "subscription.created", "subscription.cancelled",
    "monitor.alert", "grant.matched",
]


@integrations_bp.route("/")
@login_required
def index():
    webhooks = WebhookEndpoint.query.filter_by(user_id=current_user.id).order_by(WebhookEndpoint.created_at.desc()).all()
    return render_template("integrations/index.html", webhooks=webhooks,
                           platforms=SUPPORTED_PLATFORMS, events=WEBHOOK_EVENTS)


@integrations_bp.route("/webhook/create", methods=["POST"])
@login_required
def create_webhook():
    url = request.form.get("url", "").strip()
    events = request.form.getlist("events")
    name = request.form.get("name", "").strip() or "Webhook"
    secret = request.form.get("secret", "").strip()

    if not url:
        flash("Webhook URL is required.", "error")
        return redirect(url_for("integrations.index"))

    webhook = WebhookEndpoint(
        user_id=current_user.id,
        name=name,
        url=url,
        events=events,
        secret=secret,
        is_active=True
    )
    db.session.add(webhook)
    db.session.commit()
    flash(f"Webhook '{name}' created.", "success")
    return redirect(url_for("integrations.index"))


@integrations_bp.route("/webhook/delete/<int:wh_id>", methods=["POST"])
@login_required
def delete_webhook(wh_id):
    wh = WebhookEndpoint.query.get_or_404(wh_id)
    if wh.user_id != current_user.id:
        flash("Access denied.", "error")
        return redirect(url_for("integrations.index"))
    db.session.delete(wh)
    db.session.commit()
    flash("Webhook deleted.", "success")
    return redirect(url_for("integrations.index"))


@integrations_bp.route("/webhook/toggle/<int:wh_id>", methods=["POST"])
@login_required
def toggle_webhook(wh_id):
    wh = WebhookEndpoint.query.get_or_404(wh_id)
    if wh.user_id != current_user.id:
        flash("Access denied.", "error")
        return redirect(url_for("integrations.index"))
    wh.is_active = not wh.is_active
    db.session.commit()
    return redirect(url_for("integrations.index"))


@integrations_bp.route("/webhook/test/<int:wh_id>", methods=["POST"])
@csrf.exempt
@login_required
def test_webhook(wh_id):
    wh = WebhookEndpoint.query.get_or_404(wh_id)
    if wh.user_id != current_user.id:
        return jsonify({"error": "Access denied"}), 403
    import aiohttp, asyncio
    payload = {
        "event": "test.ping",
        "timestamp": datetime.utcnow().isoformat(),
        "data": {"message": "Test webhook from Jadwa AI", "user_id": current_user.id}
    }
    try:
        async def send():
            headers = {"Content-Type": "application/json", "X-Jadwa-Event": "test.ping"}
            if wh.secret:
                sig = hmac.new(wh.secret.encode(), json.dumps(payload).encode(), hashlib.sha256).hexdigest()
                headers["X-Jadwa-Signature"] = sig
            async with aiohttp.ClientSession() as s:
                async with s.post(wh.url, json=payload, headers=headers, timeout=aiohttp.ClientTimeout(total=10)) as r:
                    return r.status
        status = asyncio.run(send())
        return jsonify({"status": status, "message": f"Webhook responded with {status}"})
    except Exception as e:
        return jsonify({"error": str(e)}), 500


@integrations_bp.route("/zapier/setup")
@login_required
def zapier_setup():
    return render_template("integrations/zapier_setup.html")


@integrations_bp.route("/n8n/setup")
@login_required
def n8n_setup():
    return render_template("integrations/n8n_setup.html")


@integrations_bp.route("/activity")
@login_required
def activity_feed():
    from app.models.features import Workspace, WorkspaceMember
    ws_ids = [m.workspace_id for m in WorkspaceMember.query.filter_by(user_id=current_user.id).all()]
    if ws_ids:
        activities = ActivityLog.query.filter(
            (ActivityLog.user_id == current_user.id) |
            (ActivityLog.workspace_id.in_(ws_ids))
        ).order_by(ActivityLog.created_at.desc()).limit(50).all()
    else:
        activities = ActivityLog.query.filter_by(user_id=current_user.id).order_by(
            ActivityLog.created_at.desc()).limit(50).all()
    return render_template("integrations/activity.html", activities=activities)


def fire_webhook(user_id, event, data):
    webhooks = WebhookEndpoint.query.filter_by(user_id=user_id, is_active=True).all()
    for wh in webhooks:
        if wh.events and event not in wh.events:
            continue
        payload = {"event": event, "timestamp": datetime.utcnow().isoformat(), "data": data}
        try:
            import aiohttp, asyncio
            async def send():
                headers = {"Content-Type": "application/json", "X-Jadwa-Event": event}
                if wh.secret:
                    sig = hmac.new(wh.secret.encode(), json.dumps(payload).encode(), hashlib.sha256).hexdigest()
                    headers["X-Jadwa-Signature"] = sig
                async with aiohttp.ClientSession() as s:
                    async with s.post(wh.url, json=payload, headers=headers, timeout=aiohttp.ClientTimeout(total=10)) as r:
                        return r.status
            asyncio.run(send())
        except Exception:
            pass


def log_activity(user_id, action, resource_type=None, resource_id=None, resource_name=None, workspace_id=None):
    log = ActivityLog(user_id=user_id, workspace_id=workspace_id, action=action,
                      resource_type=resource_type, resource_id=resource_id, resource_name=resource_name)
    db.session.add(log)
    db.session.commit()
