import uuid

from django.conf import settings
from django.db import models
from django.utils import timezone


class Organization(models.Model):
    """An entity that joins JM3: school, NGO, county, corporate, church, government."""

    TYPE_CHOICES = [
        ("school", "School"),
        ("ngo", "NGO"),
        ("county", "County Government"),
        ("corporate", "Corporate"),
        ("church", "Church"),
        ("government", "Government Agency"),
        ("community", "Community Group"),
    ]
    name = models.CharField(max_length=200, unique=True)
    org_type = models.CharField(max_length=20, choices=TYPE_CHOICES, default="ngo")
    contact_email = models.EmailField(blank=True)
    county = models.CharField(max_length=100, blank=True)
    member_count = models.PositiveIntegerField(default=0, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

    @property
    def trees(self):
        return self.assets.filter(asset_type="tree")

    @property
    def total_trees(self):
        return self.trees.count()

    @property
    def alive_trees(self):
        return self.trees.filter(health_status__in=["alive", "stressed"]).count()

    @property
    def survival_rate(self):
        total = self.total_trees
        return round(self.alive_trees / total * 100, 1) if total else 0.0


class Profile(models.Model):
    ROLE_CHOICES = [
        ("student", "Student"),
        ("teacher", "Teacher"),
        ("farmer", "Farmer"),
        ("nursery_manager", "Nursery Manager"),
        ("org_admin", "Organization Admin"),
        ("community", "Community Group"),
        ("jm3_admin", "JM3 Admin"),
    ]
    MANAGES_CHOICES = [
        ("trees", "Trees"),
        ("nursery", "Nursery"),
        ("both", "Trees & Nursery"),
        ("restoration", "Restoration Site"),
    ]
    USAGE_CHOICES = [
        ("individual", "Individual"),
        ("school", "School"),
        ("community", "Community Group"),
        ("organization", "Organization"),
        ("government", "Government"),
        ("other", "Other"),
    ]
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="profile")
    organization = models.ForeignKey(Organization, on_delete=models.SET_NULL, null=True, blank=True, related_name="members")
    role = models.CharField(max_length=20, choices=ROLE_CHOICES, default="farmer")
    usage_type = models.CharField(max_length=20, choices=USAGE_CHOICES, default="individual", blank=True)
    manages = models.CharField(max_length=12, choices=MANAGES_CHOICES, default="trees", blank=True)
    occupation = models.CharField(max_length=100, blank=True, help_text="Occupation for individuals (e.g. Farmer, Teacher)")
    workspace_name = models.CharField(max_length=200, blank=True, help_text="Organization / school / group name")
    phone = models.CharField(max_length=30, blank=True)
    email = models.EmailField(blank=True, help_text="Email for OTP verification")
    county = models.CharField(max_length=100, blank=True)

    def __str__(self):
        return f"{self.user.username} ({self.get_role_display()})"


class Species(models.Model):
    common_name = models.CharField(max_length=150)
    scientific_name = models.CharField(max_length=150, blank=True)
    is_indigenous = models.BooleanField(default=True)
    carbon_factor_kg_per_year = models.FloatField(
        default=10.0, help_text="Estimated kg CO2 sequestered per tree per year, used for carbon reporting."
    )

    class Meta:
        verbose_name_plural = "species"
        ordering = ["common_name"]

    def __str__(self):
        return self.common_name


class Asset(models.Model):
    """The permanent core of JM3. Everything physical is an Asset with an
    asset_type, so adding an orchard or restoration site later is a new TYPE,
    never a new model. Activities, Tasks and Media all attach here."""

    TYPES = [
        ("tree", "Tree"),
        ("nursery", "Nursery"),
        ("orchard", "Orchard Block"),
        ("forest_block", "Forest Block"),
        ("school_garden", "School Garden"),
        ("water_source", "Water Source"),
        ("seedling", "Seedling"),
    ]
    HEALTH_CHOICES = [
        ("alive", "Alive - Healthy"),
        ("stressed", "Alive - Stressed"),
        ("dead", "Dead"),
        ("unknown", "Unknown"),
    ]
    VERIFICATION_CHOICES = [
        ("verified", "Verified"),
        ("pending", "Pending"),
        ("suspicious", "Suspicious"),
    ]
    TYPE_ICONS = {
        "tree": "🌳", "nursery": "🌱", "orchard": "🍊", "forest_block": "🌲",
        "school_garden": "🏫", "water_source": "💧", "seedling": "🌱",
    }

    asset_type = models.CharField(max_length=20, choices=TYPES, default="tree")
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name="assets")
    species = models.ForeignKey(Species, on_delete=models.PROTECT, null=True, blank=True, related_name="assets")
    tag_code = models.CharField(max_length=50, unique=True, help_text="Auto-generated asset ID / QR code")
    name = models.CharField(max_length=200, blank=True, help_text="Name for nurseries, gardens, sites")
    latitude = models.FloatField()
    longitude = models.FloatField()
    county = models.CharField(max_length=100, blank=True)
    planted_date = models.DateField(default=timezone.localdate, help_text="Planted / established date")
    photo = models.ImageField(upload_to="asset_photos/", blank=True, null=True)
    health_status = models.CharField(max_length=20, choices=HEALTH_CHOICES, default="alive")

    # Verification record
    verification_status = models.CharField(max_length=20, choices=VERIFICATION_CHOICES, default="pending")
    verification_notes = models.CharField(max_length=300, blank=True)
    photo_hash = models.CharField(max_length=64, blank=True, db_index=True)
    device_info = models.CharField(max_length=200, blank=True)

    # Where a tree/seedling came from (another asset of type nursery)
    source_nursery = models.ForeignKey("self", on_delete=models.SET_NULL, null=True, blank=True, related_name="sourced_assets")
    # Nursery-type attributes
    owner_name = models.CharField(max_length=150, blank=True)
    owner_contact = models.CharField(max_length=50, blank=True)
    seedling_capacity = models.PositiveIntegerField(default=0)
    species_available = models.ManyToManyField(Species, blank=True, related_name="available_in")

    registered_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, related_name="registered_assets")
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return self.display_name

    def save(self, *args, **kwargs):
        if not self.tag_code:
            self.tag_code = f"JM3-{uuid.uuid4().hex[:8].upper()}"
        super().save(*args, **kwargs)

    # ---- helpers ----
    @property
    def is_tree(self):
        return self.asset_type in ("tree", "seedling")

    @property
    def is_nursery(self):
        return self.asset_type == "nursery"

    @property
    def icon(self):
        return self.TYPE_ICONS.get(self.asset_type, "📍")

    @property
    def display_name(self):
        if self.name:
            return self.name
        base = self.species.common_name if self.species else self.get_asset_type_display()
        return f"{self.tag_code} ({base})"

    @property
    def location_alias(self):
        """Human location label, e.g. 'St. Mary's School' or 'Nyeri'."""
        parts = [self.organization.name if self.organization_id else "", self.county]
        return " · ".join(p for p in parts if p)

    @property
    def latest_activity(self):
        return self.activities.first()

    @property
    def last_checked(self):
        a = self.activities.filter(activity_type__in=["observed", "dead"]).first()
        return a.created_at if a else None

    @property
    def last_checked_days(self):
        from django.utils import timezone as _tz
        lc = self.last_checked
        return (_tz.now() - lc).days if lc else None

    @property
    def is_alive(self):
        return self.health_status in ("alive", "stressed")

    # ---- nursery intelligence (computed from sourced trees) ----
    @property
    def sourced_trees(self):
        return self.sourced_assets.filter(asset_type="tree").count()

    @property
    def verified_survival_rate(self):
        trees = self.sourced_assets.filter(asset_type="tree")
        total = trees.count()
        if not total:
            return None
        alive = trees.filter(health_status__in=["alive", "stressed"]).count()
        return round(alive / total * 100, 1)


class Activity(models.Model):
    """The heartbeat. Every action on an asset becomes a dated history entry —
    including monitoring (observed / dead) — so each asset has one timeline."""

    TYPES = [
        ("planted", "Planted"),
        ("watered", "Watered"),
        ("observed", "Observed"),
        ("transplanted", "Transplanted"),
        ("pruned", "Pruned"),
        ("photo", "Photo Uploaded"),
        ("verified", "Verified"),
        ("dead", "Reported Dead"),
    ]
    ICONS = {
        "planted": "🌱", "watered": "💧", "observed": "👀", "transplanted": "🪴",
        "pruned": "✂️", "photo": "📷", "verified": "✅", "dead": "❌",
    }
    DEATH_REASONS = [
        ("drought", "Drought"),
        ("pests", "Pests"),
        ("human", "Human Activity"),
        ("unknown", "Unknown"),
    ]

    asset = models.ForeignKey(Asset, on_delete=models.CASCADE, related_name="activities")
    activity_type = models.CharField(max_length=20, choices=TYPES)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, related_name="activities")
    note = models.CharField(max_length=300, blank=True)
    height_cm = models.FloatField(null=True, blank=True)
    health_status = models.CharField(max_length=20, choices=Asset.HEALTH_CHOICES, blank=True)
    death_reason = models.CharField(max_length=20, choices=DEATH_REASONS, blank=True)
    latitude = models.FloatField(null=True, blank=True)
    longitude = models.FloatField(null=True, blank=True)
    photo = models.ImageField(upload_to="activity_photos/", blank=True, null=True)
    created_at = models.DateTimeField(default=timezone.now)

    class Meta:
        ordering = ["-created_at"]
        verbose_name_plural = "activities"

    def __str__(self):
        return f"{self.asset.tag_code} {self.activity_type}"

    @property
    def icon(self):
        return self.ICONS.get(self.activity_type, "•")


class Task(models.Model):
    """The task engine. JM3 generates tasks automatically so it becomes a daily
    companion ('3 trees need checking') rather than something users forget."""

    TASK_TYPES = [
        ("check_tree", "Check tree"),
        ("review_photo", "Review photo"),
        ("water_nursery", "Water nursery"),
    ]
    STATUS = [("pending", "Pending"), ("done", "Done")]

    task_type = models.CharField(max_length=20, choices=TASK_TYPES)
    title = models.CharField(max_length=200)
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE, null=True, blank=True, related_name="tasks")
    asset = models.ForeignKey(Asset, on_delete=models.CASCADE, null=True, blank=True, related_name="tasks")
    assigned_to = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, related_name="tasks")
    status = models.CharField(max_length=10, choices=STATUS, default="pending")
    created_at = models.DateTimeField(default=timezone.now)
    completed_at = models.DateTimeField(null=True, blank=True)

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return self.title


class Media(models.Model):
    """Photos are evidence. Every captured image keeps the metadata needed for
    verification, and later for hashing onto a tamper-proof ledger."""

    asset = models.ForeignKey(Asset, on_delete=models.CASCADE, null=True, blank=True, related_name="media")
    activity = models.ForeignKey(Activity, on_delete=models.CASCADE, null=True, blank=True, related_name="media")
    image = models.ImageField(upload_to="media/")
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True)
    latitude = models.FloatField(null=True, blank=True)
    longitude = models.FloatField(null=True, blank=True)
    device = models.CharField(max_length=200, blank=True)
    sha256 = models.CharField(max_length=64, blank=True, db_index=True)
    created_at = models.DateTimeField(default=timezone.now)

    class Meta:
        ordering = ["-created_at"]
        verbose_name_plural = "media"

    def __str__(self):
        return f"Media #{self.pk}"
