from odoo import models, fields, api
from odoo.exceptions import ValidationError


class EncoachCourseSection(models.Model):
    _name = "encoach.course.section"
    _description = "Course Section Template"
    _order = "course_id, sequence, id"

    name = fields.Char(required=True)
    code = fields.Char(required=True)
    sequence = fields.Integer(default=10)
    active = fields.Boolean(default=True)
    notes = fields.Text()

    course_id = fields.Many2one("op.course", required=True, ondelete="cascade", index=True)
    entity_id = fields.Many2one(
        "encoach.entity",
        string="Entity",
        related="course_id.entity_id",
        store=True,
        index=True,
    )
    branch_id = fields.Many2one(
        "encoach.lms.branch",
        string="Branch",
        ondelete="set null",
        index=True,
        help="Optional default branch for this section template.",
    )

    batch_ids = fields.One2many("op.batch", "course_section_id", string="Batches")
    batch_count = fields.Integer(compute="_compute_batch_count")

    _sql_constraints = [
        (
            "uniq_course_section_code",
            "unique(course_id, code)",
            "Section code must be unique per course.",
        ),
    ]

    def _compute_batch_count(self):
        for rec in self:
            rec.batch_count = len(rec.batch_ids)

    @api.constrains("branch_id", "course_id")
    def _check_section_branch_entity(self):
        for rec in self:
            if (
                rec.branch_id
                and rec.course_id
                and rec.course_id.entity_id
                and rec.branch_id.entity_id != rec.course_id.entity_id
            ):
                raise ValidationError(
                    "Section branch must belong to the same entity as the course."
                )


class OpCourseExt(models.Model):
    _inherit = 'op.course'

    description = fields.Text('Description')
    max_capacity = fields.Integer('Max Capacity', default=30)
    entity_id = fields.Many2one(
        'encoach.entity',
        string='Entity',
        ondelete='set null',
        index=True,
        help='Owning entity/organization for LMS isolation.',
    )
    branch_id = fields.Many2one(
        'encoach.lms.branch',
        string='Branch',
        ondelete='set null',
        index=True,
        help='Optional branch/campus inside the owning entity.',
    )

    encoach_subject_id = fields.Many2one(
        'encoach.subject', string='Taxonomy Subject', ondelete='set null', index=True,
    )
    encoach_topic_ids = fields.Many2many(
        'encoach.topic', 'op_course_encoach_topic_rel',
        'course_id', 'topic_id', string='Topics',
    )
    learning_objective_ids = fields.Many2many(
        'encoach.learning.objective', 'op_course_learning_obj_rel',
        'course_id', 'objective_id', string='Learning Objectives',
    )
    encoach_tag_ids = fields.Many2many(
        'encoach.resource.tag', 'op_course_resource_tag_rel',
        'course_id', 'tag_id', string='Tags',
    )
    difficulty_level = fields.Selection([
        ('beginner', 'Beginner'),
        ('intermediate', 'Intermediate'),
        ('advanced', 'Advanced'),
    ])
    cefr_level = fields.Selection([
        ('pre_a1', 'Pre-A1'), ('a1', 'A1'), ('a2', 'A2'),
        ('b1', 'B1'), ('b2', 'B2'), ('c1', 'C1'), ('c2', 'C2'),
    ])

    chapter_ids = fields.One2many('encoach.course.chapter', 'course_id', string='Chapters')
    section_ids = fields.One2many(
        'encoach.course.section', 'course_id', string='Sections'
    )
    chapter_count = fields.Integer(compute='_compute_chapter_count', store=True)
    section_count = fields.Integer(compute='_compute_section_count', store=True)
    objective_count = fields.Integer(compute='_compute_objective_count')
    resource_count = fields.Integer(compute='_compute_resource_count')

    @api.depends('chapter_ids')
    def _compute_chapter_count(self):
        for rec in self:
            rec.chapter_count = len(rec.chapter_ids)

    @api.depends('section_ids')
    def _compute_section_count(self):
        for rec in self:
            rec.section_count = len(rec.section_ids)

    def _compute_objective_count(self):
        for rec in self:
            rec.objective_count = len(rec.learning_objective_ids)

    def _compute_resource_count(self):
        Mat = self.env['encoach.chapter.material'].sudo()
        for rec in self:
            mats = Mat.search([
                ('chapter_id.course_id', '=', rec.id),
                ('resource_id', '!=', False),
            ])
            rec.resource_count = len(mats.mapped('resource_id'))


class OpBatchExt(models.Model):
    _inherit = 'op.batch'

    entity_id = fields.Many2one(
        'encoach.entity',
        string='Entity',
        ondelete='set null',
        index=True,
        help='Owning entity/organization for LMS isolation.',
    )
    branch_id = fields.Many2one(
        'encoach.lms.branch',
        string='Branch',
        ondelete='set null',
        index=True,
        help='Optional branch/campus inside the owning entity.',
    )
    classroom_id = fields.Many2one(
        'op.classroom',
        string='Classroom',
        ondelete='set null',
        index=True,
        help='Classroom (homeroom) hosting this batch. When set, the batch '
             'inherits the classroom roster on course assignment.',
    )
    teacher_ids = fields.Many2many(
        'op.faculty',
        'op_batch_faculty_rel',
        'batch_id',
        'faculty_id',
        string='Teachers',
        help='Teachers assigned to this batch. A teacher may be assigned '
             'to multiple batches.',
    )
    student_count = fields.Integer(
        string='Student Count', compute='_compute_batch_student_count'
    )
    course_section_id = fields.Many2one(
        'encoach.course.section',
        string='Course Section',
        ondelete='set null',
        index=True,
        help='Specific section template of the selected course for this batch.',
    )
    term_key = fields.Char(
        string='Term Key',
        help='Optional term/semester key used for one-batch-per-term uniqueness.',
    )

    def _compute_batch_student_count(self):
        Enroll = self.env['op.student.course'].sudo()
        for rec in self:
            rec.student_count = Enroll.search_count([('batch_id', '=', rec.id)])

    @api.constrains('entity_id', 'course_id', 'classroom_id', 'course_section_id', 'branch_id')
    def _check_batch_entity_consistency(self):
        for rec in self:
            ent = rec.entity_id
            if not ent:
                continue
            if rec.course_id and rec.course_id.entity_id and rec.course_id.entity_id != ent:
                raise ValidationError(
                    "Batch course must belong to the same entity as the batch."
                )
            if rec.classroom_id and rec.classroom_id.entity_id and rec.classroom_id.entity_id != ent:
                raise ValidationError(
                    "Batch classroom must belong to the same entity as the batch."
                )
            if (
                rec.course_section_id
                and rec.course_section_id.entity_id
                and rec.course_section_id.entity_id != ent
            ):
                raise ValidationError(
                    "Batch course section must belong to the same entity as the batch."
                )
            if rec.branch_id and rec.branch_id.entity_id != ent:
                raise ValidationError(
                    "Batch branch must belong to the same entity as the batch."
                )


class OpStudentExt(models.Model):
    _inherit = 'op.student'

    entity_id = fields.Many2one(
        'encoach.entity',
        string='Entity',
        ondelete='set null',
        index=True,
        help='Owning entity/organization for LMS isolation.',
    )
    branch_id = fields.Many2one(
        'encoach.lms.branch',
        string='Branch',
        ondelete='set null',
        index=True,
        help='Optional branch/campus inside the owning entity.',
    )

    @api.constrains('branch_id', 'entity_id')
    def _check_student_branch_entity(self):
        for rec in self:
            if (
                rec.branch_id
                and rec.entity_id
                and rec.branch_id.entity_id != rec.entity_id
            ):
                raise ValidationError(
                    "Student branch must belong to the same entity as the student."
                )


class OpFacultyExt(models.Model):
    _inherit = 'op.faculty'

    entity_id = fields.Many2one(
        'encoach.entity',
        string='Entity',
        ondelete='set null',
        index=True,
        help='Owning entity/organization for LMS isolation.',
    )
    branch_id = fields.Many2one(
        'encoach.lms.branch',
        string='Branch',
        ondelete='set null',
        index=True,
        help='Optional branch/campus inside the owning entity.',
    )

    @api.constrains('branch_id', 'entity_id')
    def _check_faculty_branch_entity(self):
        for rec in self:
            if (
                rec.branch_id
                and rec.entity_id
                and rec.branch_id.entity_id != rec.entity_id
            ):
                raise ValidationError(
                    "Teacher branch must belong to the same entity as the teacher."
                )
