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

from apps.core.authentication.models import Institution
from apps.core.money import DEFAULT_CURRENCY, ISO4217_CHOICES
from apps.core.storage.paths import upload_to_scholarships
from apps.rims.grants.models import Award, GrantCall


class Scholarship(models.Model):
    """A scholarship or research-funding programme under which Scholars are enrolled.

    programme_type distinguishes the funding nature so the UI and reports can
    correctly label and group students:
      - SCHOLARSHIP: tuition + stipend awards (Mastercard, TAGDev, RECAP, DAAD)
      - RESEARCH_GRANT: thesis research grants to students/PIs (GRG, CARP+, FAPA)
      - FELLOWSHIP: post-doctoral or teaching assistantship fellowships (GTA, Post-Doc)
      - OTHER: catch-all for legacy or uncategorised programmes
    """

    class ProgrammeType(models.TextChoices):
        SCHOLARSHIP    = "scholarship",    "Scholarship"
        RESEARCH_GRANT = "research_grant", "Research Grant"
        FELLOWSHIP     = "fellowship",     "Fellowship"
        OTHER          = "other",          "Other"

    name = models.CharField(max_length=255)
    description = models.TextField(blank=True)
    programme_type = models.CharField(
        max_length=20,
        choices=ProgrammeType.choices,
        default=ProgrammeType.SCHOLARSHIP,
        db_index=True,
        help_text="Funding nature of this programme.",
    )
    grant_call = models.ForeignKey(
        GrantCall,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="scholarship_programmes",
    )
    partner = models.ForeignKey(
        "rims_operations.Partner",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="scholarship_programmes",
        help_text="Sponsor organisation for this programme.",
    )
    is_active = models.BooleanField(default=True)

    class Meta:
        ordering = ["name"]

    def __str__(self):
        return self.name


class Scholar(models.Model):
    """A scholar enrolled in a scholarship programme.

    Lifecycle: enrolled → active → paused / deferred / discontinued / withdrawn / completed.
    Transitions are gated by transition_scholar() — no django-fsm, service-level guards.
    A student self-reports their own status changes (e.g. PAUSED) with a reason.
    Staff can override at any time.
    """

    class Status(models.TextChoices):
        ENROLLED     = "enrolled",     "Enrolled"
        ACTIVE       = "active",       "Active"
        PAUSED       = "paused",       "Paused studies"
        DEFERRED     = "deferred",     "Deferred"
        DISCONTINUED = "discontinued", "Discontinued"
        WITHDRAWN    = "withdrawn",    "Withdrawn"
        COMPLETED    = "completed",    "Completed"

    class DegreeLevel(models.TextChoices):
        BACHELOR = "bachelor", "Bachelor"
        POSTGRADUATE_DIPLOMA = "pgdip", "Postgraduate Diploma"
        MPHIL    = "mphil",   "MPhil"
        MSC      = "msc",     "MSc"
        PHD      = "phd",     "PhD"
        OTHER    = "other",   "Other"

    class StudentType(models.TextChoices):
        COMPETITIVE_GRANT  = "competitive_grant",  "Competitive Grant"
        REGIONAL_PROGRAMME = "regional_programme", "Regional Programme"
        SCHOLARSHIP        = "scholarship",        "Scholarship"
        OTHER              = "other",              "Other"

    # ── Identity ─────────────────────────────────────────────────────────────
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="scholar_profiles",
    )
    scholarship = models.ForeignKey(
        Scholarship,
        on_delete=models.CASCADE,
        related_name="scholars",
    )
    award = models.OneToOneField(
        Award,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="scholar_profile",
        help_text="Link the RIMS award record when enrolled from the grants workflow.",
    )
    institution = models.ForeignKey(
        Institution,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="scholars",
    )

    # ── Academic profile ──────────────────────────────────────────────────────
    degree_level = models.CharField(
        max_length=16,
        choices=DegreeLevel.choices,
        blank=True,
        help_text="Level of degree being pursued.",
    )
    degree_name = models.CharField(
        max_length=255,
        blank=True,
        help_text="Full degree programme name, e.g. 'MSc Agricultural Economics'.",
    )
    thesis_title = models.CharField(max_length=500, blank=True)
    research_abstract = models.TextField(blank=True)
    supervisor_1 = models.CharField(max_length=255, blank=True)
    supervisor_2 = models.CharField(max_length=255, blank=True)
    supervisor_3 = models.CharField(max_length=255, blank=True)
    university_reg_no = models.CharField(
        max_length=64,
        blank=True,
        help_text="University registration / student number.",
    )
    student_number = models.CharField(max_length=64, blank=True)
    host_university_address = models.TextField(blank=True)
    student_type = models.CharField(
        max_length=24,
        choices=StudentType.choices,
        default=StudentType.OTHER,
    )

    # ── Dates ─────────────────────────────────────────────────────────────────
    cohort_year = models.PositiveSmallIntegerField(null=True, blank=True)
    intake_year = models.PositiveSmallIntegerField(null=True, blank=True)
    expected_graduation = models.DateField(
        null=True,
        blank=True,
        help_text="Planned graduation date.",
    )

    # ── Lifecycle ─────────────────────────────────────────────────────────────
    photo = models.FileField(upload_to=upload_to_scholarships, blank=True, null=True)
    notes = models.TextField(blank=True)
    enrolled_at = models.DateTimeField(auto_now_add=True)
    status = models.CharField(
        max_length=16,
        choices=Status.choices,
        default=Status.ENROLLED,
        db_index=True,
        help_text="Lifecycle stage. Use transition_scholar() to change.",
    )
    status_changed_at = models.DateTimeField(null=True, blank=True)
    status_changed_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="scholar_status_transitions",
    )
    status_reason = models.TextField(
        blank=True,
        help_text="Reason for the current status (e.g. why studies were paused).",
    )
    withdrawn_reason = models.TextField(blank=True)  # kept for backward compat

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=["user", "scholarship"],
                name="uniq_scholar_per_programme",
            ),
        ]
        ordering = ["-enrolled_at"]

    def __str__(self):
        return f"{self.user.email} — {self.scholarship}"

    @property
    def is_active_status(self):
        return self.status in (self.Status.ENROLLED, self.Status.ACTIVE)

    @property
    def supervisors(self):
        return [s for s in [self.supervisor_1, self.supervisor_2, self.supervisor_3] if s]


class Stipend(models.Model):
    """A stipend payment record for a scholar.

    SRS §4.3.4 — stipends carry a lifecycle (PENDING → PAID) so a scheduled
    payment can be cancelled when the underlying scholar is withdrawn before
    disbursement. Default is PAID so legacy rows back-fill cleanly.
    """

    class Status(models.TextChoices):
        PENDING   = "pending",   "Pending"
        PAID      = "paid",      "Paid"
        CANCELLED = "cancelled", "Cancelled"

    scholar = models.ForeignKey(Scholar, on_delete=models.CASCADE, related_name="stipends")
    amount = models.DecimalField(max_digits=12, decimal_places=2)
    currency = models.CharField(
        max_length=8,
        choices=ISO4217_CHOICES,
        default=DEFAULT_CURRENCY,
    )
    paid_on = models.DateField()
    reference = models.CharField(max_length=64, blank=True)
    status = models.CharField(
        max_length=12,
        choices=Status.choices,
        default=Status.PAID,
        db_index=True,
    )
    cancelled_at = models.DateTimeField(null=True, blank=True)
    cancelled_reason = models.TextField(blank=True)
    cancelled_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="stipends_cancelled",
    )

    class Meta:
        ordering = ["-paid_on"]


class ProgressReport(models.Model):
    """Structured periodic progress report submitted by the scholar.

    Replaces the old file-only model with full content fields that mirror
    the legacy student_reports_studentreport table, plus a review workflow.
    A file attachment is still supported for the PDF/Word version.
    """

    class Status(models.TextChoices):
        DRAFT            = "draft",            "Draft"
        SUBMITTED        = "submitted",        "Submitted"
        ACCEPTED         = "accepted",         "Accepted"
        REVISION_REQUIRED = "revision_required", "Revision required"

    scholar = models.ForeignKey(Scholar, on_delete=models.CASCADE, related_name="progress_reports")

    # ── Period ────────────────────────────────────────────────────────────────
    period_label = models.CharField(
        max_length=64,
        help_text="e.g. 'Semester 1 2026' or '2026-Q1'",
    )
    semester = models.PositiveSmallIntegerField(null=True, blank=True)
    year = models.PositiveSmallIntegerField(null=True, blank=True)

    # ── Research narrative ────────────────────────────────────────────────────
    title_of_research = models.CharField(max_length=500, blank=True)
    activities_executed = models.TextField(
        blank=True,
        help_text="Research and academic activities carried out this period.",
    )
    research_timeframe = models.TextField(blank=True)
    technology_championed = models.TextField(blank=True)
    farming_community_type = models.TextField(blank=True)
    farmers_or_organisation_count = models.PositiveIntegerField(null=True, blank=True)
    none_farmer_actors = models.TextField(blank=True)
    location = models.TextField(blank=True)
    critical_issues = models.TextField(blank=True)
    skills_required = models.TextField(blank=True)
    additional_information = models.TextField(blank=True)
    areas_university_needs_improvement = models.TextField(blank=True)

    # ── File attachment ───────────────────────────────────────────────────────
    file = models.FileField(upload_to=upload_to_scholarships, blank=True, null=True)
    notes = models.TextField(blank=True)

    # ── Workflow ──────────────────────────────────────────────────────────────
    status = models.CharField(
        max_length=20,
        choices=Status.choices,
        default=Status.DRAFT,
        db_index=True,
    )
    submitted_on = models.DateField(null=True, blank=True)
    submitted_at = models.DateTimeField(null=True, blank=True)
    accepted_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="progress_reports_accepted",
    )
    accepted_on = models.DateTimeField(null=True, blank=True)
    review_comment = models.TextField(blank=True)

    class Meta:
        ordering = ["-year", "-semester", "-submitted_at"]

    def __str__(self):
        return f"{self.scholar} — {self.period_label}"


class SupervisorFeedback(models.Model):
    """Per-supervisor feedback entry attached to a progress report."""

    report = models.ForeignKey(
        ProgressReport,
        on_delete=models.CASCADE,
        related_name="supervisor_feedbacks",
    )
    name = models.CharField(max_length=255, blank=True)
    title = models.CharField(max_length=100, blank=True)
    area_of_mentorship = models.CharField(max_length=200, blank=True)
    areas_of_achievement = models.TextField(blank=True)
    areas_requiring_attention = models.TextField(blank=True)

    class Meta:
        ordering = ["id"]

    def __str__(self):
        return f"Supervisor feedback: {self.name} — {self.report}"


class TeachingQuality(models.Model):
    """Teaching quality record attached to a progress report."""

    report = models.ForeignKey(
        ProgressReport,
        on_delete=models.CASCADE,
        related_name="teaching_quality_records",
    )
    description = models.TextField(blank=True)
    rating = models.PositiveSmallIntegerField(
        null=True,
        blank=True,
        help_text="1–5 rating where applicable.",
    )
    notes = models.TextField(blank=True)

    class Meta:
        ordering = ["id"]


class SkillsImprovement(models.Model):
    """A skill gained or improved during the reporting period."""

    report = models.ForeignKey(
        ProgressReport,
        on_delete=models.CASCADE,
        related_name="skills_improvements",
    )
    skill = models.CharField(max_length=255)
    description = models.TextField(blank=True)

    class Meta:
        ordering = ["skill"]

    def __str__(self):
        return self.skill


class Manuscript(models.Model):
    """Manuscript / journal paper linked to a progress report."""

    report = models.ForeignKey(
        ProgressReport,
        on_delete=models.CASCADE,
        related_name="manuscripts",
    )
    title = models.TextField()
    file = models.FileField(upload_to=upload_to_scholarships, blank=True, null=True)
    notes = models.TextField(blank=True)

    class Meta:
        ordering = ["title"]

    def __str__(self):
        return self.title[:80]


class ConferencePaper(models.Model):
    """Conference paper linked to a progress report."""

    report = models.ForeignKey(
        ProgressReport,
        on_delete=models.CASCADE,
        related_name="conference_papers",
    )
    title = models.TextField()
    file = models.FileField(upload_to=upload_to_scholarships, blank=True, null=True)
    notes = models.TextField(blank=True)

    class Meta:
        ordering = ["title"]

    def __str__(self):
        return self.title[:80]


class Presentation(models.Model):
    """Presentation linked to a progress report."""

    report = models.ForeignKey(
        ProgressReport,
        on_delete=models.CASCADE,
        related_name="presentations",
    )
    title = models.TextField()
    file = models.FileField(upload_to=upload_to_scholarships, blank=True, null=True)
    notes = models.TextField(blank=True)

    class Meta:
        ordering = ["title"]

    def __str__(self):
        return self.title[:80]


class GraduationRecord(models.Model):
    """Records a scholar's graduation — triggers AlumniProfile creation via signal."""

    scholar = models.OneToOneField(Scholar, on_delete=models.CASCADE, related_name="graduation")
    graduated_on = models.DateField()
    certificate_issued = models.BooleanField(default=False)
    certificate_file = models.FileField(
        upload_to=upload_to_scholarships,
        blank=True,
        null=True,
        help_text="Uploaded graduation certificate.",
    )
    notes = models.TextField(blank=True)

    class Meta:
        ordering = ["-graduated_on"]
