"""
Management command: import_weapons_csv

Reads weapon.csv (French RGA export, ';'-separated) and:
  1. Creates Caliber instances for all unique caliber names (status=VERIFIED).
  2. Creates Firearm instances for each row where the weapon type is
     mappable to a FirearmType (skips air guns, NL weapons, etc.).

CSV column layout (1-indexed, matching the header):
  1  referenceRGA
  2  famille        (EPAULE / POING)
  3  typeArme       (weapon type in French)
  4  marque         (brand)
  5  modele         (model name)
  6  fabricant
  7  paysFabricant
  8  modeFonctionnement
  9  systemeAlimentation
  10 longueurArme
  11 capaciteHorsChambre
  12 capaciteChambre
  13 calibreCanonUn  ← primary caliber
  14 modePercussionCanonUn
  15 typeCanonUn
  16 longueurCanonUn (barrel length mm)

Usage:
  python manage.py import_weapons_csv /path/to/weapon.csv
  python manage.py import_weapons_csv /path/to/weapon.csv --dry-run
"""

import csv
from django.core.management.base import BaseCommand
from django.db import transaction
from django.utils import timezone


FIREARM_TYPE_MAP = {
    'CARABINE':                                       'CARBINE',
    'CARABINE A BARILLET':                            'CARBINE',
    'FUSIL':                                          'SHOTGUN',
    "FUSIL A POMPE":                                  'SHOTGUN',
    "FUSIL D'ASSAUT":                                 'RIFLE',
    "FUSIL (FAP MODIFIE 1 COUP)":                     'SHOTGUN',
    "FUSIL SEMI-AUTOMATIQUE ET A POMPE":              'SHOTGUN',
    'PISTOLET':                                       'PISTOL',
    'REVOLVER':                                       'REVOLVER',
}


def _clean(val: str) -> str:
    """Strip surrounding whitespace and quotation marks."""
    return val.strip().strip('"').strip("'").strip()


class Command(BaseCommand):
    help = 'Import calibers and firearms from the French RGA weapon CSV.'

    def add_arguments(self, parser):
        parser.add_argument('csv_path', type=str, help='Path to weapon.csv')
        parser.add_argument(
            '--dry-run', action='store_true',
            help='Parse and count without writing to the database.',
        )

    def handle(self, *args, **options):
        from apps.calibers.models import Caliber, CaliberStatus
        from apps.gears.models import Firearm, GearStatus

        csv_path   = options['csv_path']
        dry_run    = options['dry_run']

        if dry_run:
            self.stdout.write(self.style.WARNING('DRY RUN — nothing will be saved.'))

        # ── Pass 1: collect unique caliber names ──────────────────────────────
        caliber_names = set()
        rows = []

        self.stdout.write('Reading CSV…')
        with open(csv_path, encoding='utf-8', errors='replace') as fh:
            reader = csv.reader(fh, delimiter=';')
            next(reader)  # skip header
            for row in reader:
                if len(row) < 13:
                    continue
                cal_raw = _clean(row[12])
                type_raw = _clean(row[2])
                if cal_raw and type_raw in FIREARM_TYPE_MAP:
                    caliber_names.add(cal_raw)
                rows.append(row)

        self.stdout.write(f'  {len(rows)} data rows, {len(caliber_names)} unique calibers to import.')

        if dry_run:
            fw_count = sum(
                1 for r in rows
                if len(r) >= 5 and _clean(r[2]) in FIREARM_TYPE_MAP and _clean(r[4])
            )
            self.stdout.write(f'  ~{fw_count} firearms would be created.')
            return

        # ── Pass 2: upsert Caliber instances ─────────────────────────────────
        self.stdout.write('Upserting calibers…')
        caliber_map = {}  # name → Caliber pk

        existing = {c.name: c for c in Caliber.objects.filter(name__in=caliber_names)}
        caliber_map.update({name: cal.pk for name, cal in existing.items()})

        new_calibers = []
        now = timezone.now()
        for name in caliber_names:
            if name not in existing:
                new_calibers.append(Caliber(
                    name=name,
                    status=CaliberStatus.VERIFIED,
                    reviewed_at=now,
                ))

        if new_calibers:
            created = Caliber.objects.bulk_create(new_calibers, batch_size=500)
            for c in created:
                caliber_map[c.name] = c.pk
            self.stdout.write(f'  Created {len(created)} new calibers ({len(existing)} already existed).')
        else:
            self.stdout.write(f'  All {len(existing)} calibers already existed.')

        # ── Pass 3: import firearms ───────────────────────────────────────────
        self.stdout.write('Importing firearms…')

        # Build set of existing (brand, model_name) pairs to avoid duplicates
        existing_firearms = set(
            Firearm.objects.values_list('brand', 'model_name')
        )

        to_create = []
        skipped_type = 0
        skipped_dup  = 0
        skipped_no_model = 0

        for row in rows:
            if len(row) < 5:
                continue

            type_raw   = _clean(row[2])
            firearm_type = FIREARM_TYPE_MAP.get(type_raw)
            if not firearm_type:
                skipped_type += 1
                continue

            brand     = _clean(row[3])
            model     = _clean(row[4])
            if not model:
                skipped_no_model += 1
                continue
            if not brand:
                brand = '(unknown)'

            if (brand, model) in existing_firearms:
                skipped_dup += 1
                continue

            cal_raw    = _clean(row[12]) if len(row) > 12 else ''
            cal_pk     = caliber_map.get(cal_raw) if cal_raw else None

            barrel_mm  = None
            if len(row) > 15:
                try:
                    barrel_mm = float(_clean(row[15]).replace(',', '.'))
                    if barrel_mm <= 0:
                        barrel_mm = None
                except (ValueError, AttributeError):
                    barrel_mm = None

            cap_extra  = None
            if len(row) > 10:
                try:
                    cap_extra = int(_clean(row[10]))
                except (ValueError, AttributeError):
                    pass

            to_create.append(Firearm(
                brand         = brand,
                model_name    = model,
                firearm_type  = firearm_type,
                caliber_id    = cal_pk,
                barrel_length_mm  = barrel_mm,
                magazine_capacity = cap_extra if cap_extra else None,
                status        = GearStatus.VERIFIED,
                reviewed_at   = now,
            ))
            # Track to prevent within-batch duplicates
            existing_firearms.add((brand, model))

        self.stdout.write(
            f'  {len(to_create)} firearms to create '
            f'({skipped_dup} duplicates, {skipped_type} unsupported types, '
            f'{skipped_no_model} no model name).'
        )

        with transaction.atomic():
            # Firearm inherits from Gear (MTI) so bulk_create won't work directly.
            # Use chunked individual creates instead.
            chunk = 500
            for i in range(0, len(to_create), chunk):
                batch = to_create[i:i + chunk]
                for fw in batch:
                    fw.save()
                pct = min(i + chunk, len(to_create))
                self.stdout.write(f'  … {pct}/{len(to_create)}', ending='\r')
                self.stdout.flush()

        self.stdout.write('')
        self.stdout.write(self.style.SUCCESS(
            f'Done. {len(to_create)} firearms and {len(new_calibers)} calibers imported.'
        ))
