import random
import uuid
from decimal import Decimal

from django.core.management.base import BaseCommand
from django.db import transaction

from offers.models import Offer
from suppliers.models import Supplier


# Country with approximate capital coordinates
COUNTRIES = [
    ("Russia", "RU", 55.7558, 37.6173),        # Moscow
    ("Kazakhstan", "KZ", 51.1694, 71.4491),    # Astana
    ("Uzbekistan", "UZ", 41.2995, 69.2401),    # Tashkent
    ("Turkey", "TR", 41.0082, 28.9784),        # Istanbul
    ("UAE", "AE", 25.2048, 55.2708),           # Dubai
    ("China", "CN", 31.2304, 121.4737),        # Shanghai
    ("India", "IN", 19.0760, 72.8777),         # Mumbai
    ("Germany", "DE", 52.5200, 13.4050),       # Berlin
    ("Brazil", "BR", -23.5505, -46.6333),      # Sao Paulo
]

PRODUCTS = [
    ("Steel coils", "Metals"),
    ("Aluminum ingots", "Metals"),
    ("Copper cathodes", "Metals"),
    ("Wheat grain", "Agriculture"),
    ("Corn", "Agriculture"),
    ("Sunflower oil", "Agriculture"),
    ("Coffee beans", "Agriculture"),
    ("Polyethylene granules", "Plastics"),
    ("Polypropylene granules", "Plastics"),
    ("Fertilizer NPK", "Chemicals"),
    ("Bitumen", "Chemicals"),
    ("Lumber", "Wood"),
    ("Plywood", "Wood"),
]

UNITS = ["ton", "kg", "m3", "pcs"]


class Command(BaseCommand):
    help = "Seed Suppliers and Offers with demo data"

    def add_arguments(self, parser):
        parser.add_argument(
            "--suppliers",
            type=int,
            default=100,
            help="How many suppliers to create",
        )
        parser.add_argument(
            "--offers",
            type=int,
            default=100,
            help="How many offers to create in total",
        )
        parser.add_argument(
            "--lines-per-offer",
            type=int,
            default=3,
            help="Max number of lines per offer (will randomize 1..N)",
        )
        parser.add_argument(
            "--clear",
            action="store_true",
            help="Delete all existing suppliers and offers before seeding",
        )

    @transaction.atomic
    def handle(self, *args, **options):
        if options["clear"]:
            offers_deleted, _ = Offer.objects.all().delete()
            suppliers_deleted, _ = Supplier.objects.all().delete()
            self.stdout.write(self.style.WARNING(f"Deleted {suppliers_deleted} suppliers and {offers_deleted} offers"))

        suppliers_count = max(0, options["suppliers"])
        offers_count = max(0, options["offers"])
        max_lines = max(1, options["lines_per_offer"])

        self.stdout.write(f"Creating {suppliers_count} suppliers...")
        new_suppliers = self._create_suppliers(suppliers_count)
        self.stdout.write(self.style.SUCCESS(f"Created {len(new_suppliers)} suppliers"))

        self.stdout.write(f"Creating {offers_count} offers...")
        created_offers = self._create_offers(offers_count, max_lines)
        self.stdout.write(self.style.SUCCESS(f"Created {len(created_offers)} offers"))

    def _create_suppliers(self, count: int):
        created = []
        for idx in range(count):
            team_uuid = str(uuid.uuid4())
            country, country_code, base_lat, base_lng = random.choice(COUNTRIES)
            # Add some randomness to coordinates (within ~50km)
            lat = base_lat + random.uniform(-0.5, 0.5)
            lng = base_lng + random.uniform(-0.5, 0.5)
            supplier = Supplier.objects.create(
                uuid=str(uuid.uuid4()),
                team_uuid=team_uuid,
                name=f"Supplier {idx + 1}",
                description="Demo supplier seeded for testing.",
                country=country,
                country_code=country_code,
                logo_url="",
                latitude=lat,
                longitude=lng,
                is_verified=random.choice([True, False]),
                is_active=True,
            )
            created.append(supplier)
        return created

    def _create_offers(self, count: int, max_lines: int):
        created = []
        suppliers = list(Supplier.objects.all())
        if not suppliers:
            return created

        locations = [
            ("Moscow Warehouse", "Russia", "RU", 55.7558, 37.6173),
            ("Novorossiysk Port", "Russia", "RU", 44.7237, 37.7687),
            ("Istanbul Hub", "Turkey", "TR", 41.0082, 28.9784),
            ("Dubai Jebel Ali", "UAE", "AE", 24.9857, 55.0272),
            ("Shenzhen Port", "China", "CN", 22.5431, 114.0579),
            ("Hamburg Port", "Germany", "DE", 53.5511, 9.9937),
            ("Mumbai Port", "India", "IN", 18.9388, 72.8354),
            ("Santos Port", "Brazil", "BR", -23.9608, -46.3336),
        ]

        for idx in range(count):
            supplier = random.choice(suppliers)
            product_name, category_name = random.choice(PRODUCTS)
            loc_name, loc_country, loc_code, loc_lat, loc_lng = random.choice(locations)

            offer = Offer.objects.create(
                uuid=str(uuid.uuid4()),
                team_uuid=supplier.team_uuid,
                status="active",
                # Локация
                location_uuid=str(uuid.uuid4()),
                location_name=loc_name,
                location_country=loc_country,
                location_country_code=loc_code,
                location_latitude=loc_lat,
                location_longitude=loc_lng,
                # Товар
                product_uuid=str(uuid.uuid4()),
                product_name=product_name,
                category_name=category_name,
                # Количество и цена
                quantity=self._rand_decimal(10, 500, 2),
                unit=random.choice(UNITS),
                price_per_unit=self._rand_decimal(100, 1500, 2),
                currency="USD",
                description="Demo offer seeded for testing.",
                valid_until=None,
            )

            created.append(offer)
        return created

    def _rand_decimal(self, low: int, high: int, places: int) -> Decimal:
        value = random.uniform(low, high)
        quantize_str = "1." + "0" * places
        return Decimal(str(value)).quantize(Decimal(quantize_str))
