from flask import Blueprint, render_template, request, redirect, url_for, flash
from flask_login import login_user, logout_user, login_required, current_user
from werkzeug.security import check_password_hash

from app import db
from app.models import (
    Admin, SiteSetting, PracticeArea, Partner, AboutValue,
    TeamMember, Publication, PublicationSubtopic, ContactMessage
)
from app.utils import save_upload


def _apply_image_or_link(settings, field_prefix, file_storage, url_value, subfolder):
    """Shared logic for the header-image / MD-photo style fields that can be
    set either by uploading a file or by pasting an external link.
    Whichever one was actually provided in this submission wins and the
    other is cleared, so the field stays a single source of truth."""
    path_attr = f"{field_prefix}_path"
    url_attr = f"{field_prefix}_url"

    uploaded = save_upload(file_storage, subfolder)
    url_value = (url_value or "").strip()

    if uploaded:
        setattr(settings, path_attr, uploaded)
        setattr(settings, url_attr, "")
    elif url_value and url_value != getattr(settings, url_attr):
        setattr(settings, url_attr, url_value)
        setattr(settings, path_attr, "")


admin_bp = Blueprint("admin", __name__, template_folder="../templates/admin")


# ---------------------------------------------------------------- AUTH ----
@admin_bp.route("/login", methods=["GET", "POST"])
def login():
    if current_user.is_authenticated:
        return redirect(url_for("admin.dashboard"))

    if request.method == "POST":
        username = request.form.get("username", "").strip()
        password = request.form.get("password", "")

        user = Admin.query.filter_by(username=username).first()
        if user and check_password_hash(user.password_hash, password):
            login_user(user)
            flash("Welcome back!", "success")
            return redirect(url_for("admin.dashboard"))
        flash("Invalid username or password.", "danger")

    return render_template("admin/login.html")


@admin_bp.route("/logout")
@login_required
def logout():
    logout_user()
    flash("You have been logged out.", "info")
    return redirect(url_for("admin.login"))


# ----------------------------------------------------------- DASHBOARD ----
@admin_bp.route("/")
@login_required
def dashboard():
    stats = {
        "messages": ContactMessage.query.count(),
        "unread": ContactMessage.query.filter_by(is_read=False).count(),
        "team": TeamMember.query.count(),
        "publications": Publication.query.count(),
        "practice_areas": PracticeArea.query.count(),
        "partners": Partner.query.count(),
    }
    return render_template("admin/dashboard.html", stats=stats)


# ------------------------------------------------------------ SETTINGS ----
@admin_bp.route("/settings", methods=["GET", "POST"])
@login_required
def settings():
    settings = SiteSetting.get_settings()

    if request.method == "POST":
        settings.site_name = request.form.get("site_name", settings.site_name)
        settings.phone = request.form.get("phone", "")
        settings.email = request.form.get("email", "")
        settings.address = request.form.get("address", "")
        settings.office_hours = request.form.get("office_hours", "")
        settings.registration_number = request.form.get("registration_number", "")
        settings.whatsapp_number = request.form.get("whatsapp_number", "").strip()
        settings.facebook_url = request.form.get("facebook_url", "")
        settings.instagram_url = request.form.get("instagram_url", "")
        settings.home_headline = request.form.get("home_headline", "")
        settings.home_description = request.form.get("home_description", "")
        settings.about_description = request.form.get("about_description", "")
        settings.footer_description = request.form.get("footer_description", "")
        settings.map_embed_url = request.form.get("map_embed_url", settings.map_embed_url).strip()

        settings.md_name = request.form.get("md_name", "").strip()
        settings.md_title = request.form.get("md_title", "").strip()
        settings.md_message = request.form.get("md_message", "").strip()

        logo = save_upload(request.files.get("logo"), "site")
        if logo:
            settings.logo_path = logo

        home_bg = save_upload(request.files.get("home_background"), "home")
        if home_bg:
            settings.home_background_path = home_bg

        home_photo = save_upload(request.files.get("home_photo"), "home")
        if home_photo:
            settings.home_photo_path = home_photo

        # Home background video — either an uploaded file or a pasted
        # YouTube / Vimeo / direct video link. A new upload wins over a link.
        home_bg_video = save_upload(request.files.get("home_background_video"), "home", kind="video")
        home_bg_video_url = request.form.get("home_background_video_url", "").strip()
        if home_bg_video:
            settings.home_background_video_path = home_bg_video
            settings.home_background_video_url = ""
        elif home_bg_video_url != settings.home_background_video_url:
            settings.home_background_video_url = home_bg_video_url
            settings.home_background_video_path = ""

        about_photo = save_upload(request.files.get("about_photo"), "about")
        if about_photo:
            settings.about_photo_path = about_photo

        # MD photo (upload or link)
        _apply_image_or_link(
            settings, "md_photo",
            request.files.get("md_photo"),
            request.form.get("md_photo_url"),
            "about",
        )

        # Page header banners (upload or link), one per inner page
        for page in ("about", "publications", "team", "connect"):
            _apply_image_or_link(
                settings, f"{page}_header_image",
                request.files.get(f"{page}_header_image"),
                request.form.get(f"{page}_header_image_url"),
                "headers",
            )

        db.session.commit()
        flash("Site settings updated.", "success")
        return redirect(url_for("admin.settings"))

    return render_template("admin/settings.html", settings=settings)


# -------------------------------------------------------- PRACTICE AREAS --
@admin_bp.route("/practice-areas", methods=["GET", "POST"])
@login_required
def practice_areas():
    if request.method == "POST":
        title = request.form.get("title", "").strip()
        description = request.form.get("description", "").strip()
        icon = request.form.get("icon", "scale").strip()
        order = int(request.form.get("order") or 0)
        image_path = save_upload(request.files.get("image"), "practice") or ""
        if title:
            db.session.add(PracticeArea(title=title, description=description, icon=icon, image_path=image_path, order=order))
            db.session.commit()
            flash("Practice area added.", "success")
        return redirect(url_for("admin.practice_areas"))

    items = PracticeArea.query.order_by(PracticeArea.order).all()
    return render_template("admin/practice_areas.html", items=items)


@admin_bp.route("/practice-areas/<int:item_id>/delete", methods=["POST"])
@login_required
def delete_practice_area(item_id):
    item = PracticeArea.query.get_or_404(item_id)
    db.session.delete(item)
    db.session.commit()
    flash("Practice area removed.", "info")
    return redirect(url_for("admin.practice_areas"))


# --------------------------------------------------------------- VALUES ---
@admin_bp.route("/values", methods=["GET", "POST"])
@login_required
def values():
    if request.method == "POST":
        title = request.form.get("title", "").strip()
        description = request.form.get("description", "").strip()
        icon = request.form.get("icon", "shield").strip()
        order = int(request.form.get("order") or 0)
        if title:
            db.session.add(AboutValue(title=title, description=description, icon=icon, order=order))
            db.session.commit()
            flash("Value added.", "success")
        return redirect(url_for("admin.values"))

    items = AboutValue.query.order_by(AboutValue.order).all()
    return render_template("admin/values.html", items=items)


@admin_bp.route("/values/<int:item_id>/delete", methods=["POST"])
@login_required
def delete_value(item_id):
    item = AboutValue.query.get_or_404(item_id)
    db.session.delete(item)
    db.session.commit()
    flash("Value removed.", "info")
    return redirect(url_for("admin.values"))


# ------------------------------------------------------------- PARTNERS ---
@admin_bp.route("/partners", methods=["GET", "POST"])
@login_required
def partners():
    if request.method == "POST":
        name = request.form.get("name", "").strip()
        order = int(request.form.get("order") or 0)
        logo_path = save_upload(request.files.get("logo"), "partners")
        if name and logo_path:
            db.session.add(Partner(name=name, logo_path=logo_path, order=order))
            db.session.commit()
            flash("Partner added.", "success")
        else:
            flash("Partner name and logo are required.", "danger")
        return redirect(url_for("admin.partners"))

    items = Partner.query.order_by(Partner.order).all()
    return render_template("admin/partners.html", items=items)


@admin_bp.route("/partners/<int:item_id>/delete", methods=["POST"])
@login_required
def delete_partner(item_id):
    item = Partner.query.get_or_404(item_id)
    db.session.delete(item)
    db.session.commit()
    flash("Partner removed.", "info")
    return redirect(url_for("admin.partners"))


# ---------------------------------------------------------------- TEAM ----
@admin_bp.route("/team", methods=["GET", "POST"])
@login_required
def team():
    if request.method == "POST":
        name = request.form.get("name", "").strip()
        title = request.form.get("title", "").strip()
        phone = request.form.get("phone", "").strip()
        bio = request.form.get("bio", "").strip()
        order = int(request.form.get("order") or 0)
        photo_path = save_upload(request.files.get("photo"), "team") or ""

        if name:
            db.session.add(TeamMember(
                name=name, title=title, phone=phone, bio=bio, order=order, photo_path=photo_path
            ))
            db.session.commit()
            flash("Team member added.", "success")
        return redirect(url_for("admin.team"))

    members = TeamMember.query.order_by(TeamMember.order).all()
    return render_template("admin/team.html", members=members)


@admin_bp.route("/team/<int:member_id>/delete", methods=["POST"])
@login_required
def delete_team_member(member_id):
    member = TeamMember.query.get_or_404(member_id)
    db.session.delete(member)
    db.session.commit()
    flash("Team member removed.", "info")
    return redirect(url_for("admin.team"))


# ------------------------------------------------------------ PUBLICATIONS
@admin_bp.route("/publications", methods=["GET", "POST"])
@login_required
def publications():
    if request.method == "POST":
        topic = request.form.get("title", "").strip()
        author = request.form.get("author", "").strip()
        description = request.form.get("short_description", "").strip()
        cover_path = save_upload(request.files.get("feature_picture"), "publications") or ""

        feature_video_url = request.form.get("feature_video_url", "").strip()
        feature_video_path = save_upload(
            request.files.get("feature_video_file"), "publications", kind="video"
        ) or ""

        about_description = request.form.get("about_description", "").strip()
        about_photo_path = save_upload(request.files.get("about_photo"), "publications") or ""

        is_published = bool(request.form.get("is_published"))

        if not topic:
            flash("Post title is required.", "danger")
            return redirect(url_for("admin.publications"))

        post = Publication(
            topic=topic,
            author=author,
            description=description,
            cover_image_path=cover_path,
            feature_video_url=feature_video_url,
            feature_video_path=feature_video_path,
            about_description=about_description,
            about_photo_path=about_photo_path,
            is_published=is_published,
        )
        db.session.add(post)
        db.session.flush()  # get post.id before adding subtopics

        # Subtopics arrive as parallel arrays: one description + one photo
        # per repeated "Add Subtopic" row in the form.
        sub_descriptions = request.form.getlist("subtopic_description[]")
        sub_photos = request.files.getlist("subtopic_photo[]")
        for i, sub_desc in enumerate(sub_descriptions):
            sub_desc = sub_desc.strip()
            sub_photo_file = sub_photos[i] if i < len(sub_photos) else None
            sub_photo_path = save_upload(sub_photo_file, "publications") or ""
            if sub_desc or sub_photo_path:
                db.session.add(PublicationSubtopic(
                    publication_id=post.id,
                    description=sub_desc,
                    photo_path=sub_photo_path,
                    order=i,
                ))

        db.session.commit()
        flash("Blog post published." if is_published else "Blog post saved as draft.", "success")
        return redirect(url_for("admin.publications"))

    items = Publication.query.order_by(Publication.created_at.desc()).all()
    return render_template("admin/publications.html", items=items)


@admin_bp.route("/publications/<int:pub_id>/delete", methods=["POST"])
@login_required
def delete_publication(pub_id):
    item = Publication.query.get_or_404(pub_id)
    db.session.delete(item)
    db.session.commit()
    flash("Publication removed.", "info")
    return redirect(url_for("admin.publications"))


# -------------------------------------------------------------- MESSAGES --
@admin_bp.route("/messages")
@login_required
def messages():
    items = ContactMessage.query.order_by(ContactMessage.created_at.desc()).all()
    return render_template("admin/messages.html", items=items)


@admin_bp.route("/messages/<int:msg_id>/read", methods=["POST"])
@login_required
def mark_read(msg_id):
    item = ContactMessage.query.get_or_404(msg_id)
    item.is_read = True
    db.session.commit()
    return redirect(url_for("admin.messages"))


@admin_bp.route("/messages/<int:msg_id>/delete", methods=["POST"])
@login_required
def delete_message(msg_id):
    item = ContactMessage.query.get_or_404(msg_id)
    db.session.delete(item)
    db.session.commit()
    flash("Message deleted.", "info")
    return redirect(url_for("admin.messages"))
