from __future__ import annotations

from dataclasses import dataclass
from datetime import timedelta
from decimal import Decimal

from django.db import transaction
from django.utils import timezone

from clients.models import Client
from core.choices import BillingCycle, ClientStatus, ServiceStatus, ServiceType
from core.models import Provider
from monitoring.models import MonitorCheck, MonitorIncident, WebsiteMonitor
from services.models import Service

from .models import (
    BackupRecord,
    DatabaseAsset,
    SSLCertificate,
    Server,
    TechnicalAsset,
    WordPressPlugin,
    WordPressSite,
    WordPressTheme,
)

DEMO_MARKER = "[DEMO-WP-V9.4]"


@dataclass(frozen=True)
class DemoSiteSpec:
    client: str
    domain: str
    health: str
    wp_installed: str
    wp_available: str
    php: str
    monitor_status: str
    response_ms: int | None
    http_status: int | None
    ssl_days: int
    ecommerce: bool = False
    vulnerable: bool = False
    maintenance: bool = False


DEMO_SITES = (
    DemoSiteSpec("DEMO WP — Atelier Criativo", "atelier-demo.k4w.test", WordPressSite.HealthStatus.HEALTHY, "6.7.1", "6.7.1", "8.3", WebsiteMonitor.Status.UP, 410, 200, 78),
    DemoSiteSpec("DEMO WP — Clínica Horizonte", "clinica-demo.k4w.test", WordPressSite.HealthStatus.ATTENTION, "6.6.2", "6.7.1", "8.2", WebsiteMonitor.Status.DEGRADED, 3150, 200, 24),
    DemoSiteSpec("DEMO WP — Oficina Norte", "oficina-demo.k4w.test", WordPressSite.HealthStatus.CRITICAL, "6.4.4", "6.7.1", "8.0", WebsiteMonitor.Status.DOWN, 12000, 503, -5, vulnerable=True),
    DemoSiteSpec("DEMO WP — Loja Aurora", "loja-demo.k4w.test", WordPressSite.HealthStatus.ATTENTION, "6.6.1", "6.7.1", "8.2", WebsiteMonitor.Status.UP, 980, 200, 52, ecommerce=True),
    DemoSiteSpec("DEMO WP — Associação Raiz", "raiz-demo.k4w.test", WordPressSite.HealthStatus.MAINTENANCE, "6.7.1", "6.7.1", "8.3", WebsiteMonitor.Status.MAINTENANCE, None, None, 90, maintenance=True),
    DemoSiteSpec("DEMO WP — Fotografia JM", "foto-demo.k4w.test", WordPressSite.HealthStatus.UNKNOWN, "6.5.3", "6.7.1", "8.1", WebsiteMonitor.Status.PAUSED, None, None, 12),
)


@transaction.atomic
def clear_wordpress_demo_data() -> dict[str, int]:
    clients = Client.objects.filter(internal_notes__contains=DEMO_MARKER)
    counts = {
        "clients": clients.count(),
        "sites": WordPressSite.objects.filter(notes__contains=DEMO_MARKER).count(),
        "plugins": WordPressPlugin.objects.filter(notes__contains=DEMO_MARKER).count(),
        "themes": WordPressTheme.objects.filter(notes__contains=DEMO_MARKER).count(),
        "ssl": SSLCertificate.objects.filter(notes__contains=DEMO_MARKER).count(),
        "monitors": WebsiteMonitor.objects.filter(name__startswith="DEMO WP —").count(),
    }
    Service.objects.filter(internal_notes__contains=DEMO_MARKER).delete()
    clients.delete()
    Server.objects.filter(notes__contains=DEMO_MARKER).delete()
    Provider.objects.filter(notes__contains=DEMO_MARKER).delete()
    return counts


@transaction.atomic
def seed_wordpress_demo_data(*, reset: bool = False) -> dict[str, int]:
    if reset:
        clear_wordpress_demo_data()

    now = timezone.now()
    today = timezone.localdate()

    provider, _ = Provider.objects.update_or_create(
        name="K4W Hosting DEMO V9.4",
        defaults={
            "provider_type": Provider.ProviderType.HOSTING,
            "website": "https://example.invalid/",
            "support_email": "demo-hosting@kreate4web.invalid",
            "account_reference": "Cofre DEMO / Hosting V9.4",
            "notes": f"{DEMO_MARKER} Fornecedor fictício apenas para testes.",
            "is_active": True,
        },
    )
    server, _ = Server.objects.update_or_create(
        name="Servidor WordPress DEMO V9.4",
        defaults={
            "provider": provider,
            "hostname": "wp-demo.k4w.invalid",
            "ip_address": "192.0.2.44",
            "location": "Lisboa — DEMO",
            "control_panel": "cPanel / WHM",
            "panel_url": "https://cpanel.example.invalid/",
            "account_reference": "Cofre DEMO / Servidor WordPress V9.4",
            "status": Server.Status.ACTIVE,
            "notes": f"{DEMO_MARKER} Servidor fictício para testes.",
        },
    )

    totals = {"clients": 0, "services": 0, "assets": 0, "sites": 0, "plugins": 0, "themes": 0, "ssl": 0, "monitors": 0, "checks": 0, "incidents": 0}

    for index, spec in enumerate(DEMO_SITES, start=1):
        client, created = Client.objects.update_or_create(
            name=spec.client,
            defaults={
                "client_type": Client.ClientType.COMPANY,
                "legal_name": spec.client,
                "email": f"cliente.wp{index}@example.invalid",
                "phone": f"910000{index:03d}",
                "status": ClientStatus.ACTIVE,
                "portal_access_enabled": False,
                "internal_notes": f"{DEMO_MARKER} Cliente técnico fictício. Pode ser eliminado sem afetar dados reais.",
            },
        )
        totals["clients"] += int(created)

        service, created = Service.objects.update_or_create(
            client=client,
            name=f"Manutenção WordPress — {spec.domain}",
            defaults={
                "service_type": ServiceType.MAINTENANCE,
                "provider": provider,
                "description": "Serviço fictício de manutenção WordPress para testes da V9.4.",
                "status": ServiceStatus.ATTENTION if spec.health in {WordPressSite.HealthStatus.ATTENTION, WordPressSite.HealthStatus.CRITICAL} else ServiceStatus.ACTIVE,
                "start_date": today - timedelta(days=365),
                "next_renewal_date": today + timedelta(days=45 + index * 10),
                "billing_cycle": BillingCycle.ANNUAL,
                "cost_price": Decimal("35.00"),
                "sale_price": Decimal("120.00") + Decimal(index * 15),
                "auto_renew": True,
                "is_recurring": True,
                "internal_notes": f"{DEMO_MARKER} Serviço fictício para testes.",
            },
        )
        totals["services"] += int(created)

        asset, created = TechnicalAsset.objects.update_or_create(
            service=service,
            label=f"Website {spec.domain}",
            defaults={
                "server": server,
                "asset_type": TechnicalAsset.AssetType.WEBSITE,
                "domain_name": spec.domain,
                "document_root": f"/home/demo/public_html/{spec.domain}",
                "php_version": spec.php,
                "cms": "WooCommerce" if spec.ecommerce else "WordPress",
                "cms_version": spec.wp_installed,
                "ssl_active": spec.ssl_days > 0,
                "last_checked_at": now - timedelta(hours=index),
                "status": {
                    WordPressSite.HealthStatus.HEALTHY: TechnicalAsset.Status.ACTIVE,
                    WordPressSite.HealthStatus.ATTENTION: TechnicalAsset.Status.ATTENTION,
                    WordPressSite.HealthStatus.CRITICAL: TechnicalAsset.Status.CRITICAL,
                    WordPressSite.HealthStatus.MAINTENANCE: TechnicalAsset.Status.MAINTENANCE,
                }.get(spec.health, TechnicalAsset.Status.UNKNOWN),
                "notes": f"{DEMO_MARKER} Ativo técnico fictício.",
            },
        )
        totals["assets"] += int(created)

        DatabaseAsset.objects.update_or_create(
            technical_asset=asset,
            name=f"demo_wp_{index}",
            defaults={
                "engine": DatabaseAsset.Engine.MYSQL,
                "size_mb": Decimal("128.00") + Decimal(index * 42),
                "username_reference": f"Cofre DEMO / DB / demo_wp_{index}",
                "notes": f"{DEMO_MARKER} Base de dados fictícia.",
            },
        )
        BackupRecord.objects.update_or_create(
            technical_asset=asset,
            backup_type=BackupRecord.BackupType.FULL,
            backup_date=now - timedelta(days=1),
            defaults={
                "location_reference": f"S3 DEMO / {spec.domain}",
                "size_mb": Decimal("650.00") + Decimal(index * 80),
                "verified_at": None if spec.health == WordPressSite.HealthStatus.CRITICAL else now - timedelta(hours=18),
                "status": BackupRecord.Status.FAILED if spec.health == WordPressSite.HealthStatus.CRITICAL else BackupRecord.Status.VERIFIED,
                "notes": f"{DEMO_MARKER} Backup fictício.",
            },
        )

        site, created = WordPressSite.objects.update_or_create(
            technical_asset=asset,
            defaults={
                "public_url": f"https://{spec.domain}",
                "admin_url": f"https://{spec.domain}/wp-admin/",
                "installed_version": spec.wp_installed,
                "available_version": spec.wp_available,
                "php_version": spec.php,
                "multisite": index == 5,
                "wp_cron_enabled": spec.health != WordPressSite.HealthStatus.CRITICAL,
                "automatic_core_updates": spec.health == WordPressSite.HealthStatus.HEALTHY,
                "debug_mode": spec.health == WordPressSite.HealthStatus.CRITICAL,
                "maintenance_mode": spec.maintenance,
                "credentials_reference": f"Cofre DEMO / WordPress / {spec.domain}",
                "health_status": spec.health,
                "last_updated_at": now - timedelta(days=2 if spec.health == WordPressSite.HealthStatus.HEALTHY else 47),
                "last_scan_at": now - timedelta(hours=index * 2),
                "notes": f"{DEMO_MARKER} Site WordPress fictício.",
            },
        )
        totals["sites"] += int(created)

        plugins = [
            ("Wordfence Security", "wordfence", "7.11.7", "7.11.7", WordPressPlugin.SecurityStatus.SECURE, True, False, None),
            ("Advanced Custom Fields PRO", "advanced-custom-fields-pro", "6.2.7", "6.3.1", WordPressPlugin.SecurityStatus.ATTENTION, False, True, today + timedelta(days=18)),
            ("WP Rocket", "wp-rocket", "3.16.1", "3.17.3", WordPressPlugin.SecurityStatus.ATTENTION, False, True, today + timedelta(days=50)),
            ("UpdraftPlus", "updraftplus", "1.24.5", "1.24.7", WordPressPlugin.SecurityStatus.SECURE, True, False, None),
            ("Yoast SEO", "wordpress-seo", "23.4", "24.1", WordPressPlugin.SecurityStatus.SECURE, True, False, None),
        ]
        if spec.ecommerce:
            plugins += [
                ("WooCommerce", "woocommerce", "9.1.0", "9.4.2", WordPressPlugin.SecurityStatus.ATTENTION, False, False, None),
                ("WooCommerce Stripe Gateway", "woocommerce-gateway-stripe", "8.6.0", "8.9.0", WordPressPlugin.SecurityStatus.SECURE, True, False, None),
            ]
        if spec.vulnerable:
            plugins += [
                ("Legacy Slider DEMO", "legacy-slider-demo", "1.0.0", "3.2.0", WordPressPlugin.SecurityStatus.VULNERABLE, False, False, None),
                ("Old Contact Form DEMO", "old-contact-demo", "2.1.0", "5.0.0", WordPressPlugin.SecurityStatus.VULNERABLE, False, False, None),
            ]
        for p_index, (name, slug, installed, available, security, auto, premium, expiry) in enumerate(plugins):
            _, created = WordPressPlugin.objects.update_or_create(
                wordpress_site=site,
                slug=slug,
                defaults={
                    "name": name,
                    "installed_version": installed,
                    "available_version": available,
                    "activation_status": WordPressPlugin.ActivationStatus.INACTIVE if p_index == 4 and index % 2 == 0 else WordPressPlugin.ActivationStatus.ACTIVE,
                    "automatic_updates": auto,
                    "premium": premium,
                    "provider": "Fornecedor DEMO" if premium else "WordPress.org",
                    "license_reference": f"Cofre DEMO / Licença / {slug}" if premium else "",
                    "license_expires_on": expiry,
                    "security_status": security,
                    "last_checked_at": now - timedelta(hours=index),
                    "notes": f"{DEMO_MARKER} Plugin fictício.",
                },
            )
            totals["plugins"] += int(created)

        themes = [
            ("K4W Child Theme", "k4w-child", "2.1.0", "2.1.0", True, True, "GeneratePress", False),
            ("GeneratePress Premium", "generatepress", "3.4.0", "3.5.1", False, False, "", True),
            ("Twenty Twenty-Four", "twentytwentyfour", "1.2", "1.3", False, False, "", False),
        ]
        for name, slug, installed, available, active, child, parent, premium in themes:
            _, created = WordPressTheme.objects.update_or_create(
                wordpress_site=site,
                slug=slug,
                defaults={
                    "name": name,
                    "installed_version": installed,
                    "available_version": available,
                    "is_active": active,
                    "is_child_theme": child,
                    "parent_theme": parent,
                    "automatic_updates": False,
                    "premium": premium,
                    "provider": "GeneratePress" if premium else "WordPress.org",
                    "license_reference": "Cofre DEMO / GeneratePress" if premium else "",
                    "license_expires_on": today + timedelta(days=80) if premium else None,
                    "last_checked_at": now - timedelta(hours=index),
                    "notes": f"{DEMO_MARKER} Tema fictício.",
                },
            )
            totals["themes"] += int(created)

        expires_at = now + timedelta(days=spec.ssl_days) if spec.ssl_days >= 0 else now - timedelta(days=abs(spec.ssl_days))
        ssl_status = (
            SSLCertificate.Status.EXPIRED if spec.ssl_days < 0
            else SSLCertificate.Status.EXPIRING if spec.ssl_days <= 30
            else SSLCertificate.Status.VALID
        )
        _, created = SSLCertificate.objects.update_or_create(
            technical_asset=asset,
            defaults={
                "primary_domain": spec.domain,
                "covered_domains": f"{spec.domain}\nwww.{spec.domain}",
                "issuer": "Let's Encrypt — DEMO",
                "certificate_type": SSLCertificate.CertificateType.LETS_ENCRYPT,
                "issued_at": expires_at - timedelta(days=90),
                "expires_at": expires_at,
                "automatic_renewal": spec.ssl_days > 0,
                "validation_method": SSLCertificate.ValidationMethod.HTTP,
                "status": ssl_status,
                "last_checked_at": now - timedelta(hours=index),
                "error_message": "Certificado expirado para teste." if spec.ssl_days < 0 else "",
                "notes": f"{DEMO_MARKER} Certificado fictício.",
            },
        )
        totals["ssl"] += int(created)

        monitor, created = WebsiteMonitor.objects.update_or_create(
            technical_asset=asset,
            url=f"https://{spec.domain}",
            defaults={
                "name": f"DEMO WP — {spec.domain}",
                "is_active": spec.monitor_status != WebsiteMonitor.Status.PAUSED,
                "client_visible": True,
                "interval_minutes": 5,
                "timeout_seconds": 12,
                "warning_response_ms": 2500,
                "status": spec.monitor_status,
                "maintenance_until": now + timedelta(hours=6) if spec.monitor_status == WebsiteMonitor.Status.MAINTENANCE else None,
                "last_checked_at": now - timedelta(minutes=5) if spec.response_ms else None,
                "next_check_at": now + timedelta(minutes=5) if spec.monitor_status not in {WebsiteMonitor.Status.PAUSED, WebsiteMonitor.Status.MAINTENANCE} else None,
                "last_success_at": now - timedelta(minutes=5) if spec.monitor_status in {WebsiteMonitor.Status.UP, WebsiteMonitor.Status.DEGRADED} else None,
                "last_failure_at": now - timedelta(minutes=5) if spec.monitor_status == WebsiteMonitor.Status.DOWN else None,
                "last_response_ms": spec.response_ms,
                "last_http_status": spec.http_status,
                "last_error": "HTTP 503 fictício para teste." if spec.monitor_status == WebsiteMonitor.Status.DOWN else "",
                "consecutive_failures": 3 if spec.monitor_status == WebsiteMonitor.Status.DOWN else 0,
                "consecutive_successes": 8 if spec.monitor_status in {WebsiteMonitor.Status.UP, WebsiteMonitor.Status.DEGRADED} else 0,
            },
        )
        totals["monitors"] += int(created)

        # Gera três verificações históricas por monitor sem duplicar em execuções repetidas.
        if not monitor.checks.exists():
            for offset in range(3, 0, -1):
                result = {
                    WebsiteMonitor.Status.DOWN: MonitorCheck.Result.DOWN,
                    WebsiteMonitor.Status.DEGRADED: MonitorCheck.Result.DEGRADED,
                    WebsiteMonitor.Status.MAINTENANCE: MonitorCheck.Result.MAINTENANCE,
                    WebsiteMonitor.Status.PAUSED: MonitorCheck.Result.SKIPPED,
                }.get(spec.monitor_status, MonitorCheck.Result.UP)
                MonitorCheck.objects.create(
                    monitor=monitor,
                    checked_at=now - timedelta(hours=offset),
                    result=result,
                    http_status=spec.http_status,
                    response_time_ms=spec.response_ms,
                    final_url=f"https://{spec.domain}" if spec.http_status else "",
                    ssl_valid=spec.ssl_days >= 0,
                    ssl_issuer="Let's Encrypt — DEMO",
                    ssl_expires_at=expires_at,
                    ssl_days_remaining=spec.ssl_days,
                    error_type=MonitorCheck.ErrorType.HTTP if result == MonitorCheck.Result.DOWN else "",
                    error_message="HTTP 503 fictício." if result == MonitorCheck.Result.DOWN else "",
                    details={"demo": True, "marker": DEMO_MARKER},
                )
                totals["checks"] += 1
        if spec.monitor_status == WebsiteMonitor.Status.DOWN and not monitor.incidents.filter(status__in=[MonitorIncident.Status.OPEN, MonitorIncident.Status.ACKNOWLEDGED]).exists():
            first_check = monitor.checks.order_by("checked_at").first()
            MonitorIncident.objects.create(
                monitor=monitor,
                title=f"Website indisponível — {spec.domain}",
                reason=f"{DEMO_MARKER} Incidente fictício provocado por respostas HTTP 503.",
                severity=MonitorIncident.Severity.CRITICAL,
                status=MonitorIncident.Status.OPEN,
                opened_at=now - timedelta(hours=2),
                first_check=first_check,
                last_check=monitor.checks.order_by("-checked_at").first(),
                failure_count=3,
                client_visible=True,
            )
            totals["incidents"] += 1

    # Contagens finais para a interface, mesmo em execuções idempotentes.
    totals.update({
        "clients_total": Client.objects.filter(internal_notes__contains=DEMO_MARKER).count(),
        "sites_total": WordPressSite.objects.filter(notes__contains=DEMO_MARKER).count(),
        "plugins_total": WordPressPlugin.objects.filter(notes__contains=DEMO_MARKER).count(),
        "themes_total": WordPressTheme.objects.filter(notes__contains=DEMO_MARKER).count(),
        "ssl_total": SSLCertificate.objects.filter(notes__contains=DEMO_MARKER).count(),
        "monitors_total": WebsiteMonitor.objects.filter(name__startswith="DEMO WP —").count(),
    })
    return totals
