"""Seed ~100 tasks across projects, events, and common/standalone work.

Distribution:
  - ~40 project tasks  (linked to projects.Project, requires those to exist)
  - ~30 event tasks    (linked to events.Event)
  - ~30 common tasks    (no project/event link)

35 tasks are assigned to admin@gmail.com. Every task needs created_by; admin
is the creator for all of them. Project/event links degrade gracefully — if
no projects or events exist yet, those slots fall back to common tasks.

Usage:
    python manage.py seed_tasks
    python manage.py seed_tasks --reset   # delete all tasks first, then reseed
"""
from datetime import timedelta

from django.contrib.auth import get_user_model
from django.core.management.base import BaseCommand
from django.db import transaction
from django.utils import timezone

User = get_user_model()

ADMIN_EMAIL = "admin@gmail.com"

STATUSES = ["todo", "in_progress", "review", "done", "cancelled"]
PRIORITIES = ["low", "medium", "high", "urgent"]

# Verb pools to generate varied, realistic titles without external data.
PROJECT_VERBS = [
    "Draft inception report for",
    "Prepare budget revision for",
    "Submit progress report for",
    "Schedule field research for",
    "Review deliverables for",
    "Coordinate partner meeting for",
    "Finalize literature review for",
    "Process disbursement for",
    "Plan dissemination for",
    "Compile findings for",
]
EVENT_VERBS = [
    "Confirm venue logistics for",
    "Send speaker invitations for",
    "Prepare run-of-show for",
    "Coordinate registration desk for",
    "Design backdrop and materials for",
    "Brief moderators for",
    "Arrange catering for",
    "Set up livestream for",
    "Compile attendee list for",
    "Draft press release for",
]
COMMON_TASKS = [
    "Update staff directory",
    "Reconcile petty cash for the month",
    "Renew office insurance policy",
    "Review IT security patches",
    "Onboard new research intern",
    "Archive Q1 project files",
    "Schedule quarterly all-hands meeting",
    "Audit asset inventory",
    "Update website team page",
    "Process vendor invoices",
    "Plan annual leave roster",
    "Backup shared drive",
    "Review procurement requests",
    "Prepare board meeting deck",
    "Update emergency contact list",
    "Test fire alarm system",
    "Refresh meeting room booking system",
    "Draft internal newsletter",
    "Review subscription renewals",
    "Clean up email distribution lists",
    "Update org chart",
    "Coordinate annual health check",
    "Review travel reimbursement claims",
    "Set up new laptop for hire",
    "Audit access permissions",
    "Plan team-building activity",
    "Update social media calendar",
    "Review contract renewals",
    "Compile monthly KPI dashboard",
    "Organize document shredding",
]


class Command(BaseCommand):
    help = "Seed ~100 tasks (project, event, common); 35 assigned to admin."

    def add_arguments(self, parser):
        parser.add_argument(
            "--reset", action="store_true",
            help="Delete all existing tasks before seeding.",
        )

    @transaction.atomic
    def handle(self, *args, **opts):
        from apps.tasks.models import Task

        admin = User.objects.filter(email=ADMIN_EMAIL).first()
        if not admin:
            self.stderr.write(self.style.ERROR(
                f"No user {ADMIN_EMAIL}. Run seed_demo first."))
            return

        if opts["reset"]:
            n = Task.objects.count()
            Task.objects.all().delete()
            self.stdout.write(self.style.WARNING(f"Deleted {n} existing tasks."))

        from apps.projects.models import Project
        from apps.events.models import Event

        projects = list(Project.objects.all())
        events = list(Event.objects.all())
        now = timezone.now()

        # Build the full task spec list deterministically (index drives variety).
        specs = []  # (title, project, event, tags)

        # ~40 project tasks
        for i in range(40):
            if projects:
                proj = projects[i % len(projects)]
                title = f"{PROJECT_VERBS[i % len(PROJECT_VERBS)]} {proj.name}"
                specs.append((title, proj, None, ["project"]))
            else:
                specs.append((COMMON_TASKS[i % len(COMMON_TASKS)], None, None, ["general"]))

        # ~30 event tasks
        for i in range(30):
            if events:
                evt = events[i % len(events)]
                title = f"{EVENT_VERBS[i % len(EVENT_VERBS)]} {evt.name}"
                specs.append((title, None, evt, ["event"]))
            else:
                specs.append((COMMON_TASKS[i % len(COMMON_TASKS)], None, None, ["general"]))

        # ~30 common tasks
        for i in range(30):
            specs.append((COMMON_TASKS[i % len(COMMON_TASKS)], None, None, ["general"]))

        # First 35 specs go to admin; rest get no assignee (unassigned).
        created = 0
        admin_count = 0
        done_ids = []
        for i, (title, proj, evt, tags) in enumerate(specs):
            assignee = admin if i < 35 else None
            status = STATUSES[i % len(STATUSES)]
            task = Task(
                title=title,
                description=f"{title}. Auto-seeded task.",
                status=status,
                priority=PRIORITIES[i % len(PRIORITIES)],
                assignee=assignee,
                project=proj,
                event=evt,
                due_date=now + timedelta(days=(i % 21) - 7),
                tags=tags,
                created_by=admin,
            )
            if status == "done":
                task.approved_at = now - timedelta(days=i % 5)
            task.save()
            created += 1
            if assignee == admin:
                admin_count += 1
            if status == "done":
                done_ids.append(task.id)

        # Spread completed_at across the past year so the Completion Activity
        # graph (frontend/components/contribution-graph.tsx) has visible data
        # instead of every "done" task landing on today. Task.save() always
        # stamps completed_at=now on a done transition, so backdate via a bulk
        # .update() (skips save()) after the fact, deterministic by index.
        for i, task_id in enumerate(done_ids):
            days_ago = (i * 37 + i * i * 3) % 365
            Task.objects.filter(pk=task_id).update(
                completed_at=now - timedelta(days=days_ago, hours=i % 8)
            )

        self.stdout.write(self.style.SUCCESS(
            f"Seeded {created} tasks ({admin_count} assigned to {ADMIN_EMAIL})."))
        self.stdout.write(
            f"  project-linked: {Task.objects.exclude(project=None).count()} | "
            f"event-linked: {Task.objects.exclude(event=None).count()} | "
            f"done (backdated): {len(done_ids)}")
