from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.views import LoginView, LogoutView
from django.db.models import Sum
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse, reverse_lazy
from django.utils import timezone
from django.views.decorators.http import require_POST
from django.views.generic import CreateView, DeleteView, ListView, TemplateView, UpdateView

from blog.models import Category, Comment, Post, Tag
from careers.models import Certificate, Education, Experience, Project, Skill
from core.models import ContactMessage, SiteSetting
from profiles.models import Profile, SocialLink

from .forms import (
    CategoryForm,
    CertificateForm,
    EducationForm,
    ExperienceForm,
    PostForm,
    ProfileForm,
    ProjectForm,
    SiteSettingForm,
    SkillForm,
    SocialLinkForm,
    TagForm,
)


# --------------------------------------------------------------------------- auth
class DashboardLoginView(LoginView):
    template_name = "dashboard/login.html"
    redirect_authenticated_user = True

    def form_invalid(self, form):
        messages.error(self.request, "Username atau password salah.")
        return super().form_invalid(form)


class DashboardLogoutView(LogoutView):
    next_page = reverse_lazy("core:home")


# --------------------------------------------------------------------------- base
class DashboardMixin(LoginRequiredMixin):
    login_url = reverse_lazy("dashboard:login")


class CrudListView(DashboardMixin, ListView):
    """List generik: subclass cukup mengisi meta di bawah."""

    template_name = "dashboard/generic_list.html"
    paginate_by = 20
    page_title = ""
    page_subtitle = ""
    create_url = ""
    update_url = ""
    delete_url = ""
    columns = []
    reorder_key = ""
    search_fields = []

    def get_queryset(self):
        qs = super().get_queryset()
        q = self.request.GET.get("q", "").strip()
        if q and self.search_fields:
            from django.db.models import Q

            cond = Q()
            for field in self.search_fields:
                cond |= Q(**{f"{field}__icontains": q})
            qs = qs.filter(cond)
        return qs

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx.update(
            {
                "page_title": self.page_title,
                "page_subtitle": self.page_subtitle,
                "create_url": self.create_url,
                "update_url": self.update_url,
                "delete_url": self.delete_url,
                "columns": self.columns,
                "reorder_key": self.reorder_key,
                "searchable": bool(self.search_fields),
                "query": self.request.GET.get("q", ""),
            }
        )
        return ctx


class CrudCreateView(DashboardMixin, CreateView):
    template_name = "dashboard/generic_form.html"
    page_title = ""
    cancel_url = ""

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["page_title"] = self.page_title
        ctx["cancel_url"] = self.cancel_url
        ctx["mode"] = "create"
        return ctx

    def form_valid(self, form):
        messages.success(self.request, "Data berhasil ditambahkan.")
        return super().form_valid(form)

    def form_invalid(self, form):
        messages.error(self.request, "Gagal menyimpan. Periksa isian yang ditandai merah.")
        return super().form_invalid(form)


class CrudUpdateView(DashboardMixin, UpdateView):
    template_name = "dashboard/generic_form.html"
    page_title = ""
    cancel_url = ""

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["page_title"] = self.page_title
        ctx["cancel_url"] = self.cancel_url
        ctx["mode"] = "update"
        return ctx

    def form_valid(self, form):
        messages.success(self.request, "Perubahan berhasil disimpan.")
        return super().form_valid(form)

    def form_invalid(self, form):
        messages.error(self.request, "Gagal menyimpan. Periksa isian yang ditandai merah.")
        return super().form_invalid(form)


class CrudDeleteView(DashboardMixin, DeleteView):
    template_name = "dashboard/generic_confirm_delete.html"
    page_title = "Hapus data"

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["page_title"] = self.page_title
        ctx["cancel_url"] = self.success_url
        return ctx

    def form_valid(self, form):
        messages.success(self.request, "Data berhasil dihapus.")
        return super().form_valid(form)


# --------------------------------------------------------------------------- overview
class DashboardIndexView(DashboardMixin, TemplateView):
    template_name = "dashboard/index.html"

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        total_views = Post.objects.aggregate(n=Sum("views_count"))["n"] or 0
        published = Post.published.count()
        drafts = Post.objects.filter(status="draft").count()
        ctx.update(
            {
                "count_post": Post.objects.count(),
                "count_published": published,
                "count_draft": drafts,
                "post_summary": f"{published} terbit · {drafts} draft",
                "count_experience": Experience.objects.count(),
                "count_project": Project.objects.count(),
                "count_skill": Skill.objects.count(),
                "count_certificate": Certificate.objects.count(),
                "total_views": total_views,
                "unread_messages": ContactMessage.objects.filter(is_read=False).count(),
                "pending_comments": Comment.objects.filter(is_approved=False).count(),
                "recent_posts": Post.objects.select_related("category")[:5],
                "recent_messages": ContactMessage.objects.all()[:5],
                "recent_comments": Comment.objects.select_related("post").order_by("-created_at")[:5],
            }
        )
        return ctx


# --------------------------------------------------------------------------- profil
@login_required(login_url=reverse_lazy("dashboard:login"))
def profile_edit(request):
    profile = Profile.get_solo()
    if request.method == "POST":
        form = ProfileForm(request.POST, request.FILES, instance=profile)
        if form.is_valid():
            form.save()
            messages.success(request, "Profil berhasil diperbarui.")
            return redirect("dashboard:profile")
        messages.error(request, "Gagal menyimpan profil.")
    else:
        form = ProfileForm(instance=profile)
    return render(
        request,
        "dashboard/profile_form.html",
        {
            "form": form,
            "profile": profile,
            "page_title": "Profil Saya",
            "social_links": profile.social_links.all(),
        },
    )


@login_required(login_url=reverse_lazy("dashboard:login"))
def site_setting_edit(request):
    setting = SiteSetting.get_solo()
    if request.method == "POST":
        form = SiteSettingForm(request.POST, request.FILES, instance=setting)
        if form.is_valid():
            form.save()
            messages.success(request, "Pengaturan situs disimpan.")
            return redirect("dashboard:setting")
        messages.error(request, "Gagal menyimpan pengaturan.")
    else:
        form = SiteSettingForm(instance=setting)
    return render(
        request,
        "dashboard/generic_form.html",
        {"form": form, "page_title": "Pengaturan Situs", "cancel_url": "dashboard:index", "mode": "update"},
    )


# --------------------------------------------------------------------------- social link
class SocialLinkListView(CrudListView):
    model = SocialLink
    page_title = "Social Links"
    page_subtitle = "Tautan sosial media yang tampil di header & footer"
    create_url = "dashboard:social_create"
    update_url = "dashboard:social_update"
    delete_url = "dashboard:social_delete"
    reorder_key = "social"
    columns = [
        {"label": "Platform", "field": "get_platform_display"},
        {"label": "URL", "field": "url", "type": "url"},
        {"label": "Urutan", "field": "order"},
        {"label": "Tampil", "field": "is_active", "type": "bool"},
    ]


class SocialLinkCreateView(CrudCreateView):
    model = SocialLink
    form_class = SocialLinkForm
    page_title = "Tambah Social Link"
    cancel_url = "dashboard:social_list"
    success_url = reverse_lazy("dashboard:social_list")

    def form_valid(self, form):
        form.instance.profile = Profile.get_solo()
        return super().form_valid(form)


class SocialLinkUpdateView(CrudUpdateView):
    model = SocialLink
    form_class = SocialLinkForm
    page_title = "Edit Social Link"
    cancel_url = "dashboard:social_list"
    success_url = reverse_lazy("dashboard:social_list")


class SocialLinkDeleteView(CrudDeleteView):
    model = SocialLink
    success_url = reverse_lazy("dashboard:social_list")


# --------------------------------------------------------------------------- experience
class ExperienceListView(CrudListView):
    model = Experience
    page_title = "Pengalaman Kerja"
    page_subtitle = "Riwayat karier yang tampil di timeline"
    create_url = "dashboard:experience_create"
    update_url = "dashboard:experience_update"
    delete_url = "dashboard:experience_delete"
    reorder_key = "experience"
    search_fields = ["company", "position"]
    columns = [
        {"label": "Posisi", "field": "position", "type": "strong"},
        {"label": "Perusahaan", "field": "company"},
        {"label": "Periode", "field": "period"},
        {"label": "Durasi", "field": "duration"},
        {"label": "Tampil", "field": "is_published", "type": "bool"},
    ]


class ExperienceCreateView(CrudCreateView):
    model = Experience
    form_class = ExperienceForm
    page_title = "Tambah Pengalaman Kerja"
    cancel_url = "dashboard:experience_list"
    success_url = reverse_lazy("dashboard:experience_list")


class ExperienceUpdateView(CrudUpdateView):
    model = Experience
    form_class = ExperienceForm
    page_title = "Edit Pengalaman Kerja"
    cancel_url = "dashboard:experience_list"
    success_url = reverse_lazy("dashboard:experience_list")


class ExperienceDeleteView(CrudDeleteView):
    model = Experience
    success_url = reverse_lazy("dashboard:experience_list")


# --------------------------------------------------------------------------- education
class EducationListView(CrudListView):
    model = Education
    page_title = "Pendidikan"
    page_subtitle = "Riwayat pendidikan formal & non-formal"
    create_url = "dashboard:education_create"
    update_url = "dashboard:education_update"
    delete_url = "dashboard:education_delete"
    reorder_key = "education"
    search_fields = ["school", "degree", "field_of_study"]
    columns = [
        {"label": "Institusi", "field": "school", "type": "strong"},
        {"label": "Jenjang", "field": "degree"},
        {"label": "Jurusan", "field": "field_of_study"},
        {"label": "Periode", "field": "period"},
        {"label": "Tampil", "field": "is_published", "type": "bool"},
    ]


class EducationCreateView(CrudCreateView):
    model = Education
    form_class = EducationForm
    page_title = "Tambah Pendidikan"
    cancel_url = "dashboard:education_list"
    success_url = reverse_lazy("dashboard:education_list")


class EducationUpdateView(CrudUpdateView):
    model = Education
    form_class = EducationForm
    page_title = "Edit Pendidikan"
    cancel_url = "dashboard:education_list"
    success_url = reverse_lazy("dashboard:education_list")


class EducationDeleteView(CrudDeleteView):
    model = Education
    success_url = reverse_lazy("dashboard:education_list")


# --------------------------------------------------------------------------- skill
class SkillListView(CrudListView):
    model = Skill
    page_title = "Skill"
    page_subtitle = "Keahlian yang tampil di halaman tentang & proyek"
    create_url = "dashboard:skill_create"
    update_url = "dashboard:skill_update"
    delete_url = "dashboard:skill_delete"
    reorder_key = "skill"
    search_fields = ["name"]
    columns = [
        {"label": "Nama", "field": "name", "type": "strong"},
        {"label": "Kategori", "field": "get_category_display"},
        {"label": "Level", "field": "level", "type": "level"},
        {"label": "Unggulan", "field": "is_featured", "type": "bool"},
    ]


class SkillCreateView(CrudCreateView):
    model = Skill
    form_class = SkillForm
    page_title = "Tambah Skill"
    cancel_url = "dashboard:skill_list"
    success_url = reverse_lazy("dashboard:skill_list")


class SkillUpdateView(CrudUpdateView):
    model = Skill
    form_class = SkillForm
    page_title = "Edit Skill"
    cancel_url = "dashboard:skill_list"
    success_url = reverse_lazy("dashboard:skill_list")


class SkillDeleteView(CrudDeleteView):
    model = Skill
    success_url = reverse_lazy("dashboard:skill_list")


# --------------------------------------------------------------------------- certificate
class CertificateListView(CrudListView):
    model = Certificate
    page_title = "Sertifikat"
    page_subtitle = "Sertifikasi & penghargaan"
    create_url = "dashboard:certificate_create"
    update_url = "dashboard:certificate_update"
    delete_url = "dashboard:certificate_delete"
    reorder_key = "certificate"
    search_fields = ["name", "issuer"]
    columns = [
        {"label": "Nama", "field": "name", "type": "strong"},
        {"label": "Penerbit", "field": "issuer"},
        {"label": "Terbit", "field": "issue_date", "type": "date"},
        {"label": "Tampil", "field": "is_published", "type": "bool"},
    ]


class CertificateCreateView(CrudCreateView):
    model = Certificate
    form_class = CertificateForm
    page_title = "Tambah Sertifikat"
    cancel_url = "dashboard:certificate_list"
    success_url = reverse_lazy("dashboard:certificate_list")


class CertificateUpdateView(CrudUpdateView):
    model = Certificate
    form_class = CertificateForm
    page_title = "Edit Sertifikat"
    cancel_url = "dashboard:certificate_list"
    success_url = reverse_lazy("dashboard:certificate_list")


class CertificateDeleteView(CrudDeleteView):
    model = Certificate
    success_url = reverse_lazy("dashboard:certificate_list")


# --------------------------------------------------------------------------- project
class ProjectListView(CrudListView):
    model = Project
    page_title = "Proyek"
    page_subtitle = "Portofolio yang tampil di halaman proyek"
    create_url = "dashboard:project_create"
    update_url = "dashboard:project_update"
    delete_url = "dashboard:project_delete"
    reorder_key = "project"
    search_fields = ["title", "short_description", "client"]
    columns = [
        {"label": "Judul", "field": "title", "type": "strong"},
        {"label": "Status", "field": "get_status_display"},
        {"label": "Klien", "field": "client"},
        {"label": "Unggulan", "field": "is_featured", "type": "bool"},
        {"label": "Tampil", "field": "is_published", "type": "bool"},
    ]


class ProjectCreateView(CrudCreateView):
    model = Project
    form_class = ProjectForm
    page_title = "Tambah Proyek"
    cancel_url = "dashboard:project_list"
    success_url = reverse_lazy("dashboard:project_list")


class ProjectUpdateView(CrudUpdateView):
    model = Project
    form_class = ProjectForm
    page_title = "Edit Proyek"
    cancel_url = "dashboard:project_list"
    success_url = reverse_lazy("dashboard:project_list")


class ProjectDeleteView(CrudDeleteView):
    model = Project
    success_url = reverse_lazy("dashboard:project_list")


# --------------------------------------------------------------------------- post
class PostListView(CrudListView):
    model = Post
    template_name = "dashboard/post_list.html"
    page_title = "Postingan"
    page_subtitle = "Tulis, jadwalkan, dan kelola semua postingan"
    create_url = "dashboard:post_create"
    update_url = "dashboard:post_update"
    delete_url = "dashboard:post_delete"
    search_fields = ["title", "excerpt"]

    def get_queryset(self):
        qs = super().get_queryset().select_related("category")
        status = self.request.GET.get("status")
        if status in {"draft", "published"}:
            qs = qs.filter(status=status)
        return qs

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["active_status"] = self.request.GET.get("status", "")
        return ctx


class PostCreateView(CrudCreateView):
    model = Post
    form_class = PostForm
    template_name = "dashboard/post_form.html"
    page_title = "Tulis Postingan"
    cancel_url = "dashboard:post_list"
    success_url = reverse_lazy("dashboard:post_list")


class PostUpdateView(CrudUpdateView):
    model = Post
    form_class = PostForm
    template_name = "dashboard/post_form.html"
    page_title = "Edit Postingan"
    cancel_url = "dashboard:post_list"
    success_url = reverse_lazy("dashboard:post_list")


class PostDeleteView(CrudDeleteView):
    model = Post
    success_url = reverse_lazy("dashboard:post_list")


@login_required(login_url=reverse_lazy("dashboard:login"))
@require_POST
def post_toggle_status(request, pk):
    post = get_object_or_404(Post, pk=pk)
    if post.status == "published":
        post.status = "draft"
    else:
        post.status = "published"
        if post.published_at is None:
            post.published_at = timezone.now()
    post.save()
    messages.success(request, f"Status '{post.title}' diubah ke {post.get_status_display()}.")
    return redirect("dashboard:post_list")


# --------------------------------------------------------------------------- category & tag
class CategoryListView(CrudListView):
    model = Category
    page_title = "Kategori"
    page_subtitle = "Pengelompokan postingan"
    create_url = "dashboard:category_create"
    update_url = "dashboard:category_update"
    delete_url = "dashboard:category_delete"
    search_fields = ["name"]
    columns = [
        {"label": "Nama", "field": "name", "type": "strong"},
        {"label": "Slug", "field": "slug"},
        {"label": "Deskripsi", "field": "description"},
    ]


class CategoryCreateView(CrudCreateView):
    model = Category
    form_class = CategoryForm
    page_title = "Tambah Kategori"
    cancel_url = "dashboard:category_list"
    success_url = reverse_lazy("dashboard:category_list")


class CategoryUpdateView(CrudUpdateView):
    model = Category
    form_class = CategoryForm
    page_title = "Edit Kategori"
    cancel_url = "dashboard:category_list"
    success_url = reverse_lazy("dashboard:category_list")


class CategoryDeleteView(CrudDeleteView):
    model = Category
    success_url = reverse_lazy("dashboard:category_list")


class TagListView(CrudListView):
    model = Tag
    page_title = "Tag"
    page_subtitle = "Label pendukung untuk pencarian"
    create_url = "dashboard:tag_create"
    update_url = "dashboard:tag_update"
    delete_url = "dashboard:tag_delete"
    search_fields = ["name"]
    columns = [
        {"label": "Nama", "field": "name", "type": "strong"},
        {"label": "Slug", "field": "slug"},
    ]


class TagCreateView(CrudCreateView):
    model = Tag
    form_class = TagForm
    page_title = "Tambah Tag"
    cancel_url = "dashboard:tag_list"
    success_url = reverse_lazy("dashboard:tag_list")


class TagUpdateView(CrudUpdateView):
    model = Tag
    form_class = TagForm
    page_title = "Edit Tag"
    cancel_url = "dashboard:tag_list"
    success_url = reverse_lazy("dashboard:tag_list")


class TagDeleteView(CrudDeleteView):
    model = Tag
    success_url = reverse_lazy("dashboard:tag_list")


# --------------------------------------------------------------------------- komentar
class CommentModerationView(DashboardMixin, ListView):
    model = Comment
    template_name = "dashboard/comment_list.html"
    context_object_name = "comments"
    paginate_by = 25

    def get_queryset(self):
        qs = Comment.objects.select_related("post").order_by("-created_at")
        state = self.request.GET.get("state")
        if state == "pending":
            qs = qs.filter(is_approved=False)
        elif state == "approved":
            qs = qs.filter(is_approved=True)
        return qs

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["page_title"] = "Moderasi Komentar"
        ctx["active_state"] = self.request.GET.get("state", "")
        ctx["pending_count"] = Comment.objects.filter(is_approved=False).count()
        return ctx


@login_required(login_url=reverse_lazy("dashboard:login"))
@require_POST
def comment_approve(request, pk):
    comment = get_object_or_404(Comment, pk=pk)
    comment.is_approved = not comment.is_approved
    comment.save(update_fields=["is_approved"])
    messages.success(request, "Status komentar diperbarui.")
    return redirect(request.META.get("HTTP_REFERER", reverse("dashboard:comment_list")))


@login_required(login_url=reverse_lazy("dashboard:login"))
@require_POST
def comment_delete(request, pk):
    comment = get_object_or_404(Comment, pk=pk)
    comment.delete()
    messages.success(request, "Komentar dihapus.")
    return redirect(request.META.get("HTTP_REFERER", reverse("dashboard:comment_list")))


# --------------------------------------------------------------------------- pesan masuk
class InboxView(DashboardMixin, ListView):
    model = ContactMessage
    template_name = "dashboard/inbox.html"
    context_object_name = "items"
    paginate_by = 20

    def get_queryset(self):
        qs = ContactMessage.objects.all()
        state = self.request.GET.get("state")
        if state == "unread":
            qs = qs.filter(is_read=False)
        elif state == "starred":
            qs = qs.filter(is_starred=True)
        return qs

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["page_title"] = "Pesan Masuk"
        ctx["active_state"] = self.request.GET.get("state", "")
        ctx["unread_count"] = ContactMessage.objects.filter(is_read=False).count()
        return ctx


@login_required(login_url=reverse_lazy("dashboard:login"))
def message_detail(request, pk):
    item = get_object_or_404(ContactMessage, pk=pk)
    if not item.is_read:
        item.is_read = True
        item.save(update_fields=["is_read"])
    return render(request, "dashboard/message_detail.html", {"item": item, "page_title": "Detail Pesan"})


@login_required(login_url=reverse_lazy("dashboard:login"))
@require_POST
def message_star(request, pk):
    item = get_object_or_404(ContactMessage, pk=pk)
    item.is_starred = not item.is_starred
    item.save(update_fields=["is_starred"])
    return redirect(request.META.get("HTTP_REFERER", reverse("dashboard:inbox")))


@login_required(login_url=reverse_lazy("dashboard:login"))
@require_POST
def message_delete(request, pk):
    get_object_or_404(ContactMessage, pk=pk).delete()
    messages.success(request, "Pesan dihapus.")
    return redirect("dashboard:inbox")


# --------------------------------------------------------------------------- reorder
REORDER_MODELS = {
    "experience": (Experience, "dashboard:experience_list"),
    "education": (Education, "dashboard:education_list"),
    "skill": (Skill, "dashboard:skill_list"),
    "certificate": (Certificate, "dashboard:certificate_list"),
    "project": (Project, "dashboard:project_list"),
    "social": (SocialLink, "dashboard:social_list"),
}


@login_required(login_url=reverse_lazy("dashboard:login"))
@require_POST
def reorder(request, key, pk, direction):
    if key not in REORDER_MODELS:
        return JsonResponse({"ok": False}, status=400)
    model, redirect_name = REORDER_MODELS[key]
    obj = get_object_or_404(model, pk=pk)
    delta = -1 if direction == "up" else 1
    obj.order = max(0, obj.order + delta)
    obj.save(update_fields=["order"])
    return redirect(redirect_name)
