"""Import sign-in history from the legacy WordPress site.

WordPress core keeps no last-login date; Wordfence does, in `wp_wfLogins`.
Without this the portal's owners page says "never" for everyone who has not
signed in since the rebuild, which makes it useless for the question the
client actually asks: who still uses this site?

Export first — the portal never connects to the WordPress database, the same
rule `import_wordpress` follows by taking a manifest:

    srv-gw db-query --project <wp-project> --format json --rows 100000 \
      "SELECT username, ctime, fail FROM wp_wfLogins WHERE fail=0" \
      > data/import/<site>-logins.json

    manage.py import_login_history --file /data/import/<site>-logins.json

Idempotent: rows are keyed on (user, source, occurred_at), so re-running
imports nothing new.
"""
import datetime
import json

from django.contrib.auth import get_user_model
from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone

from accounts.models import LoginEvent

User = get_user_model()


class Command(BaseCommand):
    help = "Import WordPress (Wordfence) sign-in history as LoginEvent rows."

    def add_arguments(self, parser):
        parser.add_argument("--file", required=True)
        parser.add_argument("--dry-run", action="store_true")

    def handle(self, *args, **options):
        try:
            with open(options["file"]) as handle:
                rows = json.load(handle)
        except (OSError, ValueError) as exc:
            raise CommandError("could not read %s: %s" % (options["file"], exc))
        if not isinstance(rows, list):
            raise CommandError("expected a JSON list of login rows")

        # Match on username: the portal's accounts were migrated from these
        # same WordPress users, so the usernames line up. Anything that does
        # not match is reported rather than guessed at.
        by_name = {u.username.lower(): u for u in User.objects.all()}
        by_email = {u.email.lower(): u for u in User.objects.all() if u.email}

        made = skipped = unmatched = 0
        missing = set()
        for row in rows:
            if str(row.get("fail", 0)).split(".")[0] not in ("0", ""):
                continue
            name = (row.get("username") or "").strip()
            user = by_name.get(name.lower()) or by_email.get(name.lower())
            if user is None:
                unmatched += 1
                if name:
                    missing.add(name)
                continue
            try:
                when = datetime.datetime.fromtimestamp(
                    float(row["ctime"]), tz=datetime.timezone.utc)
            except (KeyError, TypeError, ValueError):
                continue
            if when > timezone.now():        # a clock-skewed row is not history
                continue
            if LoginEvent.objects.filter(
                    user=user, source=LoginEvent.WORDPRESS, occurred_at=when).exists():
                skipped += 1
                continue
            if not options["dry_run"]:
                LoginEvent.objects.create(
                    user=user, username=user.username, succeeded=True,
                    ip=None, user_agent="", source=LoginEvent.WORDPRESS,
                    occurred_at=when,
                )
            made += 1

        self.stdout.write(
            "imported %d, already present %d, unmatched %d%s"
            % (made, skipped, unmatched,
               " (%s)" % ", ".join(sorted(missing)[:8]) if missing else ""))
