from django.db import models
from django.db.models.functions import Lower

from account.models import User
from contest.models import Contest
from utils.constants import Difficulty
from utils.models import RichTextField


class ProblemTag(models.Model):
    name = models.TextField()

    class Meta:
        db_table = "problem_tag"
        constraints = [
            models.UniqueConstraint(Lower("name"), name="problem_tag_name_ci_unique"),
        ]

    def save(self, *args, **kwargs):
        self.name = (self.name or "").strip()
        super().save(*args, **kwargs)


class Problem(models.Model):
    # display ID
    _id = models.TextField(db_index=True)
    contest = models.ForeignKey(Contest, null=True, on_delete=models.CASCADE)
    # for contest problem
    is_public = models.BooleanField(default=False, db_default=False)
    title = models.TextField()
    # HTML
    description = RichTextField()
    input_description = RichTextField()
    output_description = RichTextField()
    # [{input: "test", output: "123"}, {input: "test123", output: "456"}]
    samples = models.JSONField()
    test_case_id = models.TextField()
    # [{"input_name": "1.in", "output_name": "1.out", "score": 0}]
    test_case_score = models.JSONField()
    hint = RichTextField(null=True)
    languages = models.JSONField()
    template = models.JSONField()
    create_time = models.DateTimeField(auto_now_add=True)
    # we can not use auto_now here
    last_update_time = models.DateTimeField(auto_now=True, null=True)
    created_by = models.ForeignKey(User, on_delete=models.CASCADE)
    # ms
    time_limit = models.IntegerField()
    # MB
    memory_limit = models.IntegerField()
    visible = models.BooleanField(default=True, db_default=True)
    difficulty = models.TextField(choices=Difficulty.choices)
    tags = models.ManyToManyField(ProblemTag)
    source = models.TextField(null=True)
    # 预留：题目考察知识点，供未来 AI 分析使用（当前未接线）
    prompt = models.TextField(null=True)
    # [{language: "python", code: "..."}]
    answers = models.JSONField(null=True)
    submission_number = models.BigIntegerField(default=0, db_default=0)
    accepted_number = models.BigIntegerField(default=0, db_default=0)
    # {JudgeStatus.ACCEPTED: 3, JudgeStatus.WRONG_ANSWER: 11}, the number means count
    statistic_info = models.JSONField(default=dict, db_default=models.Value({}, output_field=models.JSONField()))
    share_submission = models.BooleanField(default=False, db_default=False)

    # 流程图相关字段
    allow_flowchart = models.BooleanField(default=False, db_default=False)
    mermaid_code = models.TextField(null=True, blank=True)
    flowchart_data = models.JSONField(default=dict, db_default=models.Value({}, output_field=models.JSONField()))
    flowchart_hint = models.TextField(null=True, blank=True)
    show_flowchart = models.BooleanField(default=False, db_default=False)

    # AST 代码结构检查规则
    ast_rules = models.JSONField(null=True, blank=True, default=None)

    # SQL 题配置: {"mode": "query"|"modify", "order_sensitive": bool}，非 SQL 题为 None
    sql_config = models.JSONField(null=True, blank=True, default=None)

    # SQL 题展示数据（保存题目时由测试点1+标准答案自动生成，见 judge/sql_runner.build_display），非 SQL 题为 None
    sql_display = models.JSONField(null=True, blank=True, default=None)

    class Meta:
        db_table = "problem"
        constraints = [
            models.UniqueConstraint(fields=["_id", "contest"], name="unique_problem_id_contest"),
        ]
        ordering = ("create_time",)
        indexes = [
            models.Index(fields=["contest", "visible"], name="problem_contest_visible_idx"),
            models.Index(fields=["visible"], name="problem_visible_idx"),
        ]

    def add_submission_number(self):
        self.submission_number = models.F("submission_number") + 1
        self.save(update_fields=["submission_number"])

    def add_ac_number(self):
        self.accepted_number = models.F("accepted_number") + 1
        self.save(update_fields=["accepted_number"])


# class ProblemSet(models):
#     title = models.CharField(max_length=20)
#     subtitle = models.CharField(max_length=50)
#     problems = models.ManyToManyField(Problem)
#     badge = models.FilePathField(path=settings.UPLOAD_DIR)
#     overviews = models.JSONField()
#     create_time = models.DateTimeField(auto_now_add=True)
#     update_time = models.DateTimeField(auto_now=True)
