from django.db import models


class City(models.Model):
    name = models.CharField(max_length=200)
    slug = models.SlugField(unique=True)
    bbox = models.JSONField(null=True, blank=True)
    place_count = models.IntegerField(default=0)

    class Meta:
        verbose_name_plural = 'Cities'
        ordering = ['name']

    def __str__(self):
        return self.name


class Category(models.Model):
    name = models.CharField(max_length=100, unique=True)

    class Meta:
        verbose_name_plural = 'Categories'
        ordering = ['name']

    def __str__(self):
        return self.name


class Place(models.Model):
    city = models.ForeignKey(City, on_delete=models.CASCADE, related_name='places')
    osm_id = models.BigIntegerField()
    osm_type = models.CharField(max_length=20)
    name = models.CharField(max_length=500)
    lat = models.FloatField()
    lon = models.FloatField()
    wikidata_qid = models.CharField(max_length=20, null=True, blank=True)
    description = models.TextField(null=True, blank=True)
    website = models.CharField(max_length=500, null=True, blank=True)
    phone = models.CharField(max_length=100, null=True, blank=True)
    opening_hours = models.CharField(max_length=500, null=True, blank=True)
    historic = models.CharField(max_length=100, null=True, blank=True)
    tourism = models.CharField(max_length=100, null=True, blank=True)
    amenity = models.CharField(max_length=100, null=True, blank=True)
    shop = models.CharField(max_length=100, null=True, blank=True)
    leisure = models.CharField(max_length=100, null=True, blank=True)
    man_made = models.CharField(max_length=100, null=True, blank=True)
    memorial = models.CharField(max_length=100, null=True, blank=True)
    artwork_type = models.CharField(max_length=100, null=True, blank=True)
    heritage = models.CharField(max_length=100, null=True, blank=True)
    pagerank = models.FloatField(null=True, blank=True)
    interest_score = models.FloatField(default=0.0, db_index=True)
    categories = models.ManyToManyField(Category, through='PlaceCategory')

    class Meta:
        unique_together = [('city', 'osm_id', 'osm_type')]
        indexes = [models.Index(fields=['-interest_score'])]
        ordering = ['-interest_score']

    def __str__(self):
        return f'{self.name} ({self.city.name})'

    def get_primary_category(self):
        """Return the most descriptive category tag value."""
        for field in ('tourism', 'historic', 'amenity', 'leisure', 'shop', 'man_made', 'artwork_type'):
            val = getattr(self, field)
            if val:
                return val.replace('_', ' ').title()
        return 'Place'

    def get_google_maps_url(self):
        return f'https://www.google.com/maps/search/?api=1&query={self.lat},{self.lon}'


class PlaceCategory(models.Model):
    place = models.ForeignKey(Place, on_delete=models.CASCADE)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)

    class Meta:
        unique_together = [('place', 'category')]

    def __str__(self):
        return f'{self.place.name} - {self.category.name}'


class PlaceImage(models.Model):
    place = models.ForeignKey(Place, on_delete=models.CASCADE, related_name='images')
    image_path = models.CharField(max_length=500)
    caption = models.CharField(max_length=500, null=True, blank=True)

    class Meta:
        ordering = ['image_path']

    def __str__(self):
        return f'Image for {self.place.name}: {self.image_path}'


class SimilarPlace(models.Model):
    main_place = models.ForeignKey(Place, on_delete=models.CASCADE, related_name='similar_to')
    similar_place = models.ForeignKey(Place, on_delete=models.CASCADE, related_name='similar_from')
    score = models.FloatField()
    method = models.CharField(max_length=50)  # 'structural', 'image_same_city', 'image_other_city'

    class Meta:
        unique_together = [('main_place', 'similar_place', 'method')]
        indexes = [models.Index(fields=['main_place', 'method', '-score'])]

    def __str__(self):
        return f'{self.main_place.name} -> {self.similar_place.name} ({self.method})'


class ImageFeature(models.Model):
    image_path = models.CharField(max_length=500, unique=True)
    city = models.ForeignKey(City, on_delete=models.CASCADE)
    category_name = models.CharField(max_length=100)
    feature_vector = models.TextField()  # JSON array of floats (30-dim: 10 colors * 3 RGB)
    place = models.ForeignKey(Place, on_delete=models.SET_NULL, null=True, blank=True, related_name='image_features')

    class Meta:
        ordering = ['image_path']

    def __str__(self):
        return f'Feature for {self.image_path}'
