"""Import bookmarks from x-bookmarks-exporter JSON dump.

Usage:
    python manage.py import_x_bookmarks /path/to/data/bookmarks
    python manage.py import_x_bookmarks /path/to/data/bookmarks_index.json
    python manage.py import_x_bookmarks /path/to/single_file.json
"""
import json
import os
from pathlib import Path

from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone
from links.models import Bookmark
from links.serializers import _norm_bookmark_for_import, compute_bookmark_content_hash


class Command(BaseCommand):
    help = 'Import bookmarks from x-bookmarks-exporter JSON files'

    def add_arguments(self, parser):
        parser.add_argument('source',
                            help='Directory of <tweet_id>.json files, a '
                                 'bookmarks_index.json, or a single bookmark JSON')
        parser.add_argument('--clear', action='store_true',
                            help='Delete all existing bookmarks before import')
        parser.add_argument('--update', action='store_true', default=True,
                            help='Upsert by tweet_id (default behaviour)')

    def handle(self, *args, **opts):
        src = opts['source']
        if not os.path.exists(src):
            raise CommandError(f'source not found: {src}')

        files = []
        if os.path.isdir(src):
            files = sorted(Path(src).glob('*.json'))
        elif os.path.isfile(src):
            files = [Path(src)]
        else:
            raise CommandError(f'invalid source: {src}')

        if opts['clear']:
            n = Bookmark.objects.count()
            Bookmark.objects.all().delete()
            self.stdout.write(f'cleared {n} existing bookmarks')

        created = updated = unchanged = skipped = 0
        for fp in files:
            try:
                with open(fp, 'r', encoding='utf-8') as f:
                    payload = json.load(f)
            except (OSError, json.JSONDecodeError) as e:
                self.stderr.write(f'skip {fp.name}: {e}')
                skipped += 1
                continue
            # allow either a single object or the index file
            if isinstance(payload, dict) and 'bookmarks' in payload:
                items = payload['bookmarks']
                # index entries don't have full data; only import if they
                # look like full objects (have 'media' or 'author').
                if items and not all(isinstance(i, dict) and
                                     ('media' in i or 'author' in i) for i in items):
                    self.stdout.write(f'skip index {fp.name} (no full payloads)')
                    skipped += len(items)
                    continue
            elif isinstance(payload, dict):
                items = [payload]
            elif isinstance(payload, list):
                items = payload
            else:
                skipped += 1
                continue

            for raw in items:
                tid = str(raw.get('id') or raw.get('tweet_id') or '')
                if not tid:
                    skipped += 1
                    continue
                new_hash = compute_bookmark_content_hash(raw)
                obj = Bookmark.objects.filter(tweet_id=tid).first()
                if obj is not None and obj.content_hash == new_hash:
                    # Content unchanged — only bump import timestamp.
                    obj.last_imported_at = timezone.now()
                    obj.save(update_fields=['last_imported_at'])
                    unchanged += 1
                    continue
                try:
                    b = _norm_bookmark_for_import(raw, obj)
                    b.save()
                except Exception as e:
                    self.stderr.write(f'err {tid}: {e}')
                    skipped += 1
                    continue
                if obj is None:
                    created += 1
                else:
                    updated += 1

        self.stdout.write(self.style.SUCCESS(
            f'import done: created={created} updated={updated} '
            f'unchanged={unchanged} skipped={skipped} '
            f'total_in_db={Bookmark.objects.count()}'))
