from datetime import timedelta

from django.contrib import admin, messages
from django.db.models import Q
from django.utils import timezone
from unfold.admin import ModelAdmin
from unfold.contrib.filters.admin import RangeDateFilter
from unfold.decorators import display

from billing.workflows import create_renewal_for_service
from core.admin_ui import PortalAdminMixin
from core.choices import ServiceStatus
from core.status_palette import SERVICE_STATUS_LABELS
from .models import Service


@admin.action(description="Marcar serviços selecionados como ativos")
def mark_active(modeladmin, request, queryset):
    queryset.update(status=ServiceStatus.ACTIVE)


@admin.action(description="Arquivar serviços selecionados")
def mark_archived(modeladmin, request, queryset):
    queryset.update(status=ServiceStatus.ARCHIVED)


@admin.action(description="Criar renovação para os serviços selecionados")
def create_renewals(modeladmin, request, queryset):
    created_count = 0
    existing_count = 0
    error_count = 0
    for service in queryset.select_related("client"):
        try:
            _, created = create_renewal_for_service(service)
            created_count += int(created)
            existing_count += int(not created)
        except ValueError:
            error_count += 1
    if created_count:
        modeladmin.message_user(request, f"Foram criadas {created_count} renovações.", messages.SUCCESS)
    if existing_count:
        modeladmin.message_user(request, f"{existing_count} renovações já existiam.", messages.INFO)
    if error_count:
        modeladmin.message_user(request, f"{error_count} serviços não puderam gerar renovação por falta de recorrência ou data.", messages.WARNING)


@admin.register(Service)
class ServiceAdmin(PortalAdminMixin, ModelAdmin):
    portal_icon = "inventory_2"
    portal_kicker = "GESTÃO COMERCIAL"
    portal_description = "Catálogo central de todos os serviços, valores, periodicidades, estados e próximas renovações."
    portal_tone = "violet"
    portal_stats = (
        {"label": "Serviços registados", "icon": "inventory_2", "tone": "primary", "caption": "Carteira total"},
        {"label": "Serviços ativos", "icon": "check_circle", "tone": "success", "filters": {"status": ServiceStatus.ACTIVE}, "caption": "Em prestação", "query": {"status__exact": ServiceStatus.ACTIVE}},
        {"label": "Renovam em 30 dias", "icon": "event_upcoming", "tone": "warning", "method": "count_upcoming", "caption": "A preparar"},
        {"label": "Dados incompletos", "icon": "data_alert", "tone": "danger", "method": "count_incomplete", "caption": "Requer revisão"},
    )
    portal_related_links = (
        {"label": "Renovações", "icon": "event_repeat", "url_name": "admin:billing_renewal_changelist"},
        {"label": "Pagamentos", "icon": "payments", "url_name": "admin:billing_payment_changelist"},
        {"label": "Domínios", "icon": "language", "url_name": "admin:domains_domain_changelist"},
    )

    list_display = (
        "service_identity",
        "client",
        "service_type",
        "show_status",
        "next_renewal_date",
        "days_remaining",
        "sale_price",
        "margin_value",
    )
    list_filter = (
        "service_type",
        "status",
        "billing_cycle",
        "provider",
        "is_recurring",
        "is_complimentary",
        ("next_renewal_date", RangeDateFilter),
    )
    search_fields = ("name", "client__name", "client__email", "description", "internal_notes")
    autocomplete_fields = ("client", "provider")
    readonly_fields = ("public_id", "created_at", "updated_at", "margin_value", "days_remaining")
    actions = (create_renewals, mark_active, mark_archived)
    list_filter_submit = True
    list_fullwidth = True

    fieldsets = (
        ("Serviço", {"fields": ("client", "service_type", "name", "provider", "description", "status"), "description": "Identificação comercial e relação com o cliente."}),
        ("Renovação", {"fields": ("is_recurring", "billing_cycle", "start_date", "next_renewal_date", "notice_days", "auto_renew"), "description": "Regras de recorrência e datas usadas nos avisos."}),
        ("Valores", {"fields": ("cost_price", "sale_price", "tax_rate", "margin_value", "is_complimentary", "customer_pays_provider_directly"), "description": "Custos internos, preço de venda e condições especiais."}),
        ("Observações", {"fields": ("internal_notes",)}),
        ("Sistema", {"fields": ("public_id", "created_at", "updated_at"), "classes": ("collapse",)}),
    )

    def count_upcoming(self, request, queryset):
        today = timezone.localdate()
        return queryset.filter(
            status=ServiceStatus.ACTIVE,
            is_recurring=True,
            next_renewal_date__range=(today, today + timedelta(days=30)),
        ).count()

    def count_incomplete(self, request, queryset):
        return queryset.filter(
            Q(client__email="") | Q(provider__isnull=True) | Q(is_recurring=True, next_renewal_date__isnull=True)
        ).distinct().count()

    @display(description="Serviço", header=True)
    def service_identity(self, obj):
        return obj.name, obj.get_service_type_display()

    @display(description="Estado", label=SERVICE_STATUS_LABELS, ordering="status")
    def show_status(self, obj):
        return obj.get_status_display()

    @display(description="Dias")
    def days_remaining(self, obj):
        value = obj.days_until_renewal
        return "—" if value is None else value

    @display(description="Margem")
    def margin_value(self, obj):
        return f"{obj.margin:.2f} €"
