from django.db import models
from django.conf import settings
from django.utils import timezone
import secrets
import time
from apps.core.uploads import own_organization_upload_path, tenant_upload_path


def uuid7() -> str:
    """Generate a UUID v7 (time-ordered UUID)."""
    nanoseconds = time.time_ns()
    uuid_int = (nanoseconds << 16) | secrets.randbits(48)
    return f"{uuid_int:032x}"


class Company(models.Model):
    """Company/organization records."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    organization = models.ForeignKey("Organization", on_delete=models.CASCADE, related_name="companies")
    name = models.CharField(max_length=255)
    abbreviation = models.CharField(max_length=20, blank=True, db_index=True,
        help_text="Short code / acronym, e.g. WHO, UNICEF.")
    slug = models.SlugField(max_length=255, blank=True, null=True)
    legal_name = models.CharField(max_length=255, blank=True)
    company_type = models.CharField(max_length=20, choices=[
        ("organization", "Organization"),
        ("donor", "Donor"),
    ], default="organization", db_index=True)
    donor_category = models.CharField(max_length=20, choices=[
        ("regular", "Regular"),
        ("project", "Project"),
    ], default="regular", db_index=True, blank=True,
       help_text="Only meaningful when company_type='donor'. Project = linked via ProjectFund.")
    industry = models.CharField(max_length=100, blank=True)
    website = models.URLField(blank=True)
    email = models.EmailField(blank=True)
    phone = models.CharField(max_length=20, blank=True)
    address = models.TextField(blank=True)
    city = models.CharField(max_length=100, blank=True)
    country = models.CharField(max_length=100, blank=True)
    tax_id = models.CharField(max_length=50, blank=True)
    pic = models.CharField(max_length=255, blank=True, help_text="Person in charge / primary contact name.")
    pic_title = models.CharField(max_length=255, blank=True, help_text="PIC position / job title.")
    logo = models.ImageField(upload_to=tenant_upload_path("company-logos"), null=True, blank=True)
    description = models.TextField(blank=True)
    notes = models.TextField(blank=True)
    tags = models.JSONField(default=list)
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "companies"
        ordering = ["name"]
        constraints = [models.UniqueConstraint(fields=["organization", "slug"], name="unique_company_slug_per_org")]

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        if not self.slug and self.name:
            self.slug = self.name.lower().replace(" ", "-")
        super().save(*args, **kwargs)


class Organization(models.Model):
    """A tenant. Users join via OrganizationMembership; branding/contact fields
    below were absorbed from the old singleton OrgProfile model."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    slug = models.SlugField(max_length=255, unique=True, blank=True)
    members = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="organizations", through="OrganizationMembership")
    name = models.CharField(max_length=255, default="My Organization")
    legal_name = models.CharField(max_length=255, blank=True)
    tagline = models.CharField(max_length=255, blank=True)
    logo = models.ImageField(upload_to=own_organization_upload_path("branding"), null=True, blank=True)
    logo_white = models.ImageField(upload_to=own_organization_upload_path("branding"), null=True, blank=True)
    logo_full = models.ImageField(upload_to=own_organization_upload_path("branding"), null=True, blank=True)
    logo_full_white = models.ImageField(upload_to=own_organization_upload_path("branding"), null=True, blank=True)
    favicon = models.ImageField(upload_to=own_organization_upload_path("branding"), null=True, blank=True)
    # Branding colors are tri-state (unset vs configured) unlike this model's other
    # CharFields, so these use null=True in addition to blank=True.
    primary_color_light = models.CharField(max_length=7, null=True, blank=True)
    primary_color_dark = models.CharField(max_length=7, null=True, blank=True)
    secondary_color_light = models.CharField(max_length=7, null=True, blank=True)
    secondary_color_dark = models.CharField(max_length=7, null=True, blank=True)
    accent_color_light = models.CharField(max_length=7, null=True, blank=True)
    accent_color_dark = models.CharField(max_length=7, null=True, blank=True)
    font_color_light = models.CharField(max_length=7, null=True, blank=True)
    font_color_dark = models.CharField(max_length=7, null=True, blank=True)
    link_color_light = models.CharField(max_length=7, null=True, blank=True)
    link_color_dark = models.CharField(max_length=7, null=True, blank=True)
    # Sidebar background. Null falls back to the primary color, which is what
    # the sidebar used unconditionally before this field existed — so an
    # organization that never sets it keeps its current look.
    sidebar_color_light = models.CharField(max_length=7, null=True, blank=True)
    sidebar_color_dark = models.CharField(max_length=7, null=True, blank=True)
    sidebar_font_color_light = models.CharField(max_length=7, null=True, blank=True)
    sidebar_font_color_dark = models.CharField(max_length=7, null=True, blank=True)
    icon_color_light = models.CharField(max_length=7, null=True, blank=True)
    icon_color_dark = models.CharField(max_length=7, null=True, blank=True)
    sidebar_active_bg_color_light = models.CharField(max_length=7, null=True, blank=True)
    sidebar_active_bg_color_dark = models.CharField(max_length=7, null=True, blank=True)
    sidebar_active_icon_color_light = models.CharField(max_length=7, null=True, blank=True)
    sidebar_active_icon_color_dark = models.CharField(max_length=7, null=True, blank=True)
    tab_active_color_light = models.CharField(max_length=7, null=True, blank=True)
    tab_active_color_dark = models.CharField(max_length=7, null=True, blank=True)
    button_color_light = models.CharField(max_length=7, null=True, blank=True)
    button_color_dark = models.CharField(max_length=7, null=True, blank=True)
    # Base hues for chart palettes (frontend derives tints/shades from these).
    # Max 4 — charts needing more series shade/step these rather than adding a 5th hue.
    chart_color_1_light = models.CharField(max_length=7, null=True, blank=True)
    chart_color_1_dark = models.CharField(max_length=7, null=True, blank=True)
    chart_color_2_light = models.CharField(max_length=7, null=True, blank=True)
    chart_color_2_dark = models.CharField(max_length=7, null=True, blank=True)
    chart_color_3_light = models.CharField(max_length=7, null=True, blank=True)
    chart_color_3_dark = models.CharField(max_length=7, null=True, blank=True)
    chart_color_4_light = models.CharField(max_length=7, null=True, blank=True)
    chart_color_4_dark = models.CharField(max_length=7, null=True, blank=True)
    email = models.EmailField(blank=True)
    phone = models.CharField(max_length=30, blank=True)
    website = models.URLField(blank=True)
    address = models.TextField(blank=True)
    city = models.CharField(max_length=100, blank=True)
    country = models.CharField(max_length=100, blank=True)
    latitude = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)
    longitude = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)
    tax_id = models.CharField(max_length=50, blank=True)
    description = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "organizations"

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        if not self.slug and self.name:
            base_slug = self.name.lower().replace(" ", "-")
            slug = base_slug
            suffix = 1
            while Organization.objects.filter(slug=slug).exclude(pk=self.pk).exists():
                suffix += 1
                slug = f"{base_slug}-{suffix}"
            self.slug = slug
        super().save(*args, **kwargs)


class OrganizationMembership(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name="memberships")
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="organization_memberships")
    is_owner = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "organization_memberships"
        constraints = [models.UniqueConstraint(fields=["organization", "user"], name="unique_org_membership")]

    def __str__(self):
        return f"{self.user_id} -> {self.organization_id}"


class Director(models.Model):
    """Board / executive director records — always linked to an Employee."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name="directors")
    employee = models.OneToOneField(
        "hr.Employee", on_delete=models.CASCADE, related_name="director_role",
    )
    title = models.CharField(max_length=255, blank=True, help_text="Director role, e.g. CEO, Board Chair")
    bio = models.TextField(blank=True, help_text="Director-specific bio shown on org profile")
    order = models.PositiveIntegerField(default=0)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "org_directors"
        ordering = ["order", "id"]

    def __str__(self):
        emp_name = self.employee.user.get_full_name() if self.employee_id else "?"
        return f"{emp_name} ({self.title})" if self.title else emp_name


class Department(models.Model):
    """Internal departments within the organization."""
    id = models.UUIDField(primary_key=True, default=uuid7, editable=False)
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name="departments")
    name = models.CharField(max_length=255)
    code = models.CharField(max_length=20, blank=True, help_text="Short code, e.g. POL, ECO")
    description = models.TextField(blank=True)
    is_research = models.BooleanField(default=False, help_text="Department conducts research")
    parent = models.ForeignKey("self", on_delete=models.SET_NULL, null=True, blank=True, related_name="children")
    head = models.ForeignKey("hr.Employee", on_delete=models.SET_NULL, null=True, blank=True, related_name="led_departments")
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "org_departments"
        ordering = ["name"]
        constraints = [models.UniqueConstraint(fields=["organization", "name"], name="unique_department_name_per_org")]

    def __str__(self):
        return self.name