# Generated by Django 5.2.12 on 2026-03-13 16:11

import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name="AnonymousSession",
            fields=[
                (
                    "session_id",
                    models.UUIDField(
                        help_text="UUID assigned by the browser client (stored in localStorage/cookie)",
                        primary_key=True,
                        serialize=False,
                    ),
                ),
                (
                    "ip_address",
                    models.GenericIPAddressField(
                        help_text="Client IP address at the time of first event"
                    ),
                ),
                (
                    "user_agent",
                    models.TextField(blank=True, default="", help_text="Browser User-Agent string"),
                ),
                (
                    "fingerprint",
                    models.CharField(
                        blank=True,
                        db_index=True,
                        default="",
                        help_text="Optional browser fingerprint hash (computed client-side)",
                        max_length=64,
                    ),
                ),
                ("first_seen", models.DateTimeField(auto_now_add=True)),
                (
                    "last_seen",
                    models.DateTimeField(
                        db_index=True,
                        default=django.utils.timezone.now,
                        help_text="Last time an event was received from this session",
                    ),
                ),
                (
                    "matched_at",
                    models.DateTimeField(
                        blank=True,
                        help_text="When this anonymous session was linked to a user",
                        null=True,
                    ),
                ),
                (
                    "user",
                    models.ForeignKey(
                        blank=True,
                        help_text="Authenticated user this session was matched to",
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="anonymous_sessions",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
            ],
            options={
                "verbose_name": "Anonymous Session",
                "verbose_name_plural": "Anonymous Sessions",
                "ordering": ["-last_seen"],
            },
        ),
        migrations.CreateModel(
            name="FrontendEvent",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                (
                    "event_type",
                    models.CharField(
                        choices=[
                            ("ERROR", "Error"),
                            ("WARNING", "Warning"),
                            ("INFO", "Info"),
                            ("PAGE_VIEW", "Page View"),
                            ("PERFORMANCE", "Performance"),
                            ("NETWORK_ERROR", "Network Error"),
                            ("JS_ERROR", "JS Error"),
                            ("CONSOLE", "Console"),
                        ],
                        db_index=True,
                        max_length=20,
                    ),
                ),
                (
                    "level",
                    models.CharField(
                        choices=[
                            ("error", "Error"),
                            ("warn", "Warning"),
                            ("info", "Info"),
                            ("debug", "Debug"),
                        ],
                        db_index=True,
                        default="info",
                        max_length=10,
                    ),
                ),
                ("message", models.TextField()),
                (
                    "stack_trace",
                    models.TextField(
                        blank=True, default="", help_text="Full stack trace for JS errors"
                    ),
                ),
                (
                    "url",
                    models.TextField(
                        blank=True, default="", help_text="Page URL where the event occurred"
                    ),
                ),
                (
                    "http_status",
                    models.PositiveSmallIntegerField(
                        blank=True, help_text="HTTP status code of the failed request", null=True
                    ),
                ),
                (
                    "http_method",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="HTTP method of the failed request",
                        max_length=10,
                    ),
                ),
                (
                    "http_url",
                    models.TextField(
                        blank=True, default="", help_text="URL of the failed API call"
                    ),
                ),
                ("user_agent", models.TextField(blank=True, default="")),
                ("ip_address", models.GenericIPAddressField()),
                (
                    "device_type",
                    models.CharField(
                        blank=True, default="", help_text="mobile / tablet / desktop", max_length=10
                    ),
                ),
                ("os", models.CharField(blank=True, default="", max_length=50)),
                ("browser", models.CharField(blank=True, default="", max_length=50)),
                (
                    "fingerprint",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Client-generated hash for deduplication (e.g. sha256 of message+stack+url)",
                        max_length=64,
                    ),
                ),
                (
                    "extra",
                    models.JSONField(
                        blank=True, default=dict, help_text="Arbitrary extra data from the client"
                    ),
                ),
                (
                    "project_name",
                    models.CharField(
                        blank=True,
                        db_index=True,
                        default="",
                        help_text="Frontend project name (useful when multiple frontends share one backend)",
                        max_length=100,
                    ),
                ),
                (
                    "environment",
                    models.CharField(
                        blank=True,
                        db_index=True,
                        default="",
                        help_text="production / staging / development",
                        max_length=20,
                    ),
                ),
                ("created_at", models.DateTimeField(auto_now_add=True, db_index=True)),
                (
                    "anonymous_session",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="events",
                        to="django_cfg_monitor.anonymoussession",
                    ),
                ),
                (
                    "user",
                    models.ForeignKey(
                        blank=True,
                        help_text="Authenticated user (null for anonymous visitors)",
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="frontend_events",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
            ],
            options={
                "verbose_name": "Frontend Event",
                "verbose_name_plural": "Frontend Events",
                "ordering": ["-created_at"],
            },
        ),
        migrations.CreateModel(
            name="ServerEvent",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                (
                    "fingerprint",
                    models.CharField(
                        db_index=True,
                        help_text="sha256(exception_type::module::func_name)[:16]. Does NOT include line numbers — stable across deploys.",
                        max_length=16,
                        unique=True,
                    ),
                ),
                (
                    "event_type",
                    models.CharField(
                        choices=[
                            ("SERVER_ERROR", "Server Error"),
                            ("UNHANDLED_EXCEPTION", "Unhandled Exception"),
                            ("SLOW_QUERY", "Slow Query"),
                            ("RQ_FAILURE", "RQ Task Failure"),
                            ("OOM_KILL", "OOM / Process Kill"),
                            ("LOG_ERROR", "Log Error"),
                        ],
                        db_index=True,
                        max_length=25,
                    ),
                ),
                (
                    "level",
                    models.CharField(
                        choices=[
                            ("error", "Error"),
                            ("warning", "Warning"),
                            ("info", "Info"),
                            ("debug", "Debug"),
                        ],
                        db_index=True,
                        default="error",
                        max_length=10,
                    ),
                ),
                (
                    "message",
                    models.TextField(help_text="Short error description or exception message"),
                ),
                (
                    "stack_trace",
                    models.TextField(
                        blank=True,
                        help_text="Full formatted traceback (sanitized — no PII)",
                        null=True,
                    ),
                ),
                (
                    "logger_name",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Python logger name (e.g. 'django.request', 'myapp.tasks')",
                        max_length=200,
                    ),
                ),
                (
                    "url",
                    models.TextField(
                        blank=True, default="", help_text="Request URL where the error occurred"
                    ),
                ),
                (
                    "http_method",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="HTTP method (GET, POST, …)",
                        max_length=10,
                    ),
                ),
                (
                    "http_status",
                    models.PositiveSmallIntegerField(
                        blank=True, help_text="HTTP status code returned to the client", null=True
                    ),
                ),
                (
                    "func_name",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Function or method name where the error originated",
                        max_length=200,
                    ),
                ),
                (
                    "module",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Python module path (e.g. 'myapp.views.orders')",
                        max_length=300,
                    ),
                ),
                (
                    "lineno",
                    models.PositiveIntegerField(
                        blank=True,
                        help_text="Line number at time of first occurrence — display only, NOT part of the fingerprint",
                        null=True,
                    ),
                ),
                (
                    "extra",
                    models.JSONField(
                        blank=True,
                        default=dict,
                        help_text="Arbitrary structured context: RQ job_id, queue name, slow query SQL, OOM process info, etc.",
                    ),
                ),
                (
                    "project_name",
                    models.CharField(
                        blank=True,
                        db_index=True,
                        default="",
                        help_text="Django project / service name",
                        max_length=100,
                    ),
                ),
                (
                    "environment",
                    models.CharField(
                        blank=True,
                        db_index=True,
                        default="",
                        help_text="production / staging / development",
                        max_length=20,
                    ),
                ),
                (
                    "occurrence_count",
                    models.IntegerField(
                        default=1, help_text="How many times this fingerprint has been seen"
                    ),
                ),
                (
                    "first_seen",
                    models.DateTimeField(
                        auto_now_add=True, help_text="When this fingerprint was first recorded"
                    ),
                ),
                (
                    "last_seen",
                    models.DateTimeField(
                        db_index=True,
                        default=django.utils.timezone.now,
                        help_text="When this fingerprint was most recently triggered",
                    ),
                ),
                (
                    "is_resolved",
                    models.BooleanField(
                        db_index=True, default=False, help_text="Marked resolved by a team member"
                    ),
                ),
                ("resolved_at", models.DateTimeField(blank=True, null=True)),
                (
                    "resolved_by",
                    models.ForeignKey(
                        blank=True,
                        help_text="User who marked this event as resolved",
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="resolved_server_events",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
            ],
            options={
                "verbose_name": "Server Event",
                "verbose_name_plural": "Server Events",
                "ordering": ["-last_seen"],
            },
        ),
        migrations.AddIndex(
            model_name="anonymoussession",
            index=models.Index(
                fields=["ip_address", "last_seen"], name="django_cfg__ip_addr_bb0f0e_idx"
            ),
        ),
        migrations.AddIndex(
            model_name="frontendevent",
            index=models.Index(
                fields=["fingerprint", "url", "created_at"], name="django_cfg__fingerp_bf96ef_idx"
            ),
        ),
        migrations.AddIndex(
            model_name="frontendevent",
            index=models.Index(
                fields=["ip_address", "event_type", "created_at"],
                name="django_cfg__ip_addr_7eddd5_idx",
            ),
        ),
        migrations.AddIndex(
            model_name="frontendevent",
            index=models.Index(
                fields=["anonymous_session", "created_at"], name="django_cfg__anonymo_5697e4_idx"
            ),
        ),
        migrations.AddIndex(
            model_name="serverevent",
            index=models.Index(fields=["fingerprint"], name="cfg_srv_fingerprint_idx"),
        ),
        migrations.AddIndex(
            model_name="serverevent",
            index=models.Index(fields=["last_seen", "is_resolved"], name="cfg_srv_last_seen_idx"),
        ),
        migrations.AddIndex(
            model_name="serverevent",
            index=models.Index(fields=["event_type", "last_seen"], name="cfg_srv_type_idx"),
        ),
        migrations.AddIndex(
            model_name="serverevent",
            index=models.Index(
                fields=["project_name", "environment", "last_seen"], name="cfg_srv_project_idx"
            ),
        ),
    ]
