from django.conf import settings
from django.db import models
from django.urls import reverse

from .uploads import project_attachment_storage, project_attachment_upload_to


class ProjectBrief(models.Model):
    STATUS_SUBMITTED = "submitted"
    STATUS_UNDER_REVIEW = "under_review"
    STATUS_QUOTED = "quoted"
    STATUS_ACCEPTED = "accepted"
    STATUS_DECLINED = "declined"
    STATUS_IN_PROGRESS = "in_progress"
    STATUS_DELIVERED = "delivered"
    STATUS_CLOSED = "closed"

    STATUS_CHOICES = [
        (STATUS_SUBMITTED, "Submitted"),
        (STATUS_UNDER_REVIEW, "Under review"),
        (STATUS_QUOTED, "Quoted"),
        (STATUS_ACCEPTED, "Accepted"),
        (STATUS_DECLINED, "Declined"),
        (STATUS_IN_PROGRESS, "In progress"),
        (STATUS_DELIVERED, "Delivered"),
        (STATUS_CLOSED, "Closed"),
    ]

    CATEGORY_WEB = "web"
    CATEGORY_DATA = "data"
    CATEGORY_RESEARCH = "research"
    CATEGORY_MEDICAL_IMAGING = "medical_imaging"
    CATEGORY_WORKFLOW = "workflow"
    CATEGORY_OTHER = "other"

    CATEGORY_CHOICES = [
        (CATEGORY_WEB, "Web development"),
        (CATEGORY_DATA, "Data & analytics"),
        (CATEGORY_RESEARCH, "Research"),
        (CATEGORY_MEDICAL_IMAGING, "Medical imaging"),
        (CATEGORY_WORKFLOW, "Workflow automation"),
        (CATEGORY_OTHER, "Other"),
    ]

    BUDGET_UNDER_5K = "under_5k"
    BUDGET_5K_15K = "5k_15k"
    BUDGET_15K_50K = "15k_50k"
    BUDGET_50K_PLUS = "50k_plus"
    BUDGET_NOT_SURE = "not_sure"

    BUDGET_CHOICES = [
        (BUDGET_UNDER_5K, "Under $5,000"),
        (BUDGET_5K_15K, "$5,000 – $15,000"),
        (BUDGET_15K_50K, "$15,000 – $50,000"),
        (BUDGET_50K_PLUS, "$50,000+"),
        (BUDGET_NOT_SURE, "Not sure yet"),
    ]

    LOCK_FIELD_MAP = {
        "title": "lock_title",
        "category": "lock_category",
        "description": "lock_description",
        "budget_range": "lock_budget_range",
        "desired_deadline": "lock_desired_deadline",
        "reference_links": "lock_reference_links",
        "attachments": "lock_attachments",
    }

    client = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="project_briefs",
    )
    title = models.CharField(max_length=300)
    category = models.CharField(max_length=32, choices=CATEGORY_CHOICES, blank=True, default="")
    description = models.TextField(
        blank=True,
        default="",
        help_text="Project scope, context, and goals combined.",
    )
    budget_range = models.CharField(max_length=32, choices=BUDGET_CHOICES, blank=True, default="")
    desired_deadline = models.DateField(blank=True, null=True)
    reference_links = models.TextField(blank=True)
    status = models.CharField(
        max_length=32,
        choices=STATUS_CHOICES,
        default=STATUS_SUBMITTED,
    )
    quote_text = models.TextField(blank=True)
    website_notes = models.TextField(
        blank=True,
        help_text="Notes from Tecvico shown to the client in the portal.",
    )
    locked = models.BooleanField(
        default=False,
        verbose_name="Lock project",
        help_text="Lock the whole project so the client cannot edit it at all.",
    )
    lock_title = models.BooleanField(default=False, help_text="Lock title for the client.")
    lock_category = models.BooleanField(default=False, help_text="Lock category for the client.")
    lock_description = models.BooleanField(
        default=False, help_text="Lock description for the client."
    )
    lock_budget_range = models.BooleanField(
        default=False, help_text="Lock budget range for the client."
    )
    lock_desired_deadline = models.BooleanField(
        default=False, help_text="Lock desired deadline for the client."
    )
    lock_reference_links = models.BooleanField(
        default=False, help_text="Lock reference links for the client."
    )
    lock_attachments = models.BooleanField(
        default=False, help_text="Lock attachments for the client."
    )
    show_on_website = models.BooleanField(
        default=False,
        help_text="Display this project in the public website showcase.",
    )
    show_title_on_website = models.BooleanField(
        default=True,
        help_text="Show the title on the website card.",
    )
    show_category_on_website = models.BooleanField(
        default=True,
        help_text="Show category as a tag on the website card.",
    )
    show_description_on_website = models.BooleanField(
        default=True,
        help_text="Use the description as the website card summary when no summary is set.",
    )
    show_budget_on_website = models.BooleanField(
        default=False,
        help_text="Show the budget range on the website card.",
    )
    show_deadline_on_website = models.BooleanField(
        default=False,
        help_text="Show the desired deadline on the website card.",
    )
    show_references_on_website = models.BooleanField(
        default=False,
        help_text="Show reference links on the website card.",
    )
    show_attachments_on_website = models.BooleanField(
        default=False,
        help_text="Show attachment filenames on the website card.",
    )
    public_title = models.CharField(
        max_length=300,
        blank=True,
        help_text="Optional showcase title. Defaults to the brief title.",
    )
    public_summary = models.TextField(
        blank=True,
        help_text="Short summary for the website project card.",
    )
    public_tags = models.CharField(
        max_length=300,
        blank=True,
        help_text="Comma-separated tags for the website card.",
    )
    public_image = models.ImageField(
        upload_to="projects/showcase/",
        blank=True,
        null=True,
        help_text="Image for the website project card.",
    )
    public_project_status = models.CharField(
        max_length=10,
        choices=[
            ("", "—"),
            ("new", "New"),
            ("ongoing", "Ongoing"),
            ("done", "Done"),
        ],
        blank=True,
        help_text="Filter category for the website showcase.",
    )
    public_url = models.CharField(
        max_length=300,
        blank=True,
        help_text="Optional link for the website project card.",
    )
    submitted_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ["-submitted_at"]
        verbose_name = "Project Brief"
        verbose_name_plural = "Project Briefs"

    def __str__(self):
        return f"{self.title} ({self.get_status_display()})"

    @property
    def is_editable_by_client(self):
        return self.status == self.STATUS_SUBMITTED and not self.locked

    def is_field_locked(self, field_name):
        if self.locked:
            return True
        attr = self.LOCK_FIELD_MAP.get(field_name)
        if attr is None:
            return False
        return getattr(self, attr)

    @property
    def attachments_locked(self):
        return self.is_field_locked("attachments")

    @property
    def shows_quote_to_client(self):
        return self.status in {
            self.STATUS_QUOTED,
            self.STATUS_ACCEPTED,
            self.STATUS_DECLINED,
            self.STATUS_IN_PROGRESS,
            self.STATUS_DELIVERED,
            self.STATUS_CLOSED,
        } and bool(self.quote_text.strip())

    @property
    def has_website_notes(self):
        return bool(self.website_notes.strip())

    @property
    def public_display_title(self):
        if not self.show_title_on_website:
            return ""
        return self.public_title.strip() or self.title

    @property
    def public_tag_list(self):
        tags = []
        if self.show_category_on_website and self.category:
            tags.append(self.get_category_display())
        if self.public_tags.strip():
            tags.extend(
                tag.strip()
                for tag in self.public_tags.split(",")
                if tag.strip()
            )
        return tags

    @property
    def public_display_summary(self):
        if self.public_summary.strip():
            return self.public_summary.strip()
        if self.show_description_on_website and self.description.strip():
            return self.description.strip()
        return ""

    @property
    def public_budget_display(self):
        if not self.show_budget_on_website or not self.budget_range:
            return ""
        return self.get_budget_range_display()

    @property
    def public_deadline_display(self):
        if not self.show_deadline_on_website or not self.desired_deadline:
            return ""
        return self.desired_deadline.strftime("%b %-d, %Y")

    @property
    def public_reference_link_list(self):
        if not self.show_references_on_website or not self.reference_links.strip():
            return []
        return [
            link.strip()
            for link in self.reference_links.splitlines()
            if link.strip()
        ]

    @property
    def public_attachment_filename_list(self):
        if not self.show_attachments_on_website:
            return []
        return list(self.attachments.values_list("original_filename", flat=True))

    def get_absolute_url(self):
        return reverse("projects:detail", kwargs={"pk": self.pk})


class ProjectBriefAttachment(models.Model):
    brief = models.ForeignKey(
        ProjectBrief,
        on_delete=models.CASCADE,
        related_name="attachments",
    )
    file = models.FileField(
        upload_to=project_attachment_upload_to,
        storage=project_attachment_storage,
    )
    original_filename = models.CharField(max_length=255)
    uploaded_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["uploaded_at"]
        verbose_name = "Project Attachment"
        verbose_name_plural = "Project Attachments"

    def __str__(self):
        return self.original_filename


class ProjectInternalNote(models.Model):
    brief = models.ForeignKey(
        ProjectBrief,
        on_delete=models.CASCADE,
        related_name="internal_notes",
    )
    author = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="project_internal_notes",
    )
    note = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-created_at"]
        verbose_name = "Internal Note"
        verbose_name_plural = "Internal Notes"

    def __str__(self):
        preview = self.note[:60]
        return f"{self.brief.title} — {preview}"
