"""Training library: vocabulary items, grammar rules and per-user progress.

Backs the `/admin/training/vocabulary` and `/admin/training/grammar` pages
(previously hard-coded mocks).
"""
from odoo import api, fields, models


CEFR_LEVELS = [
    ('A1', 'A1'),
    ('A2', 'A2'),
    ('B1', 'B1'),
    ('B2', 'B2'),
    ('C1', 'C1'),
    ('C2', 'C2'),
]


class EncoachVocabItem(models.Model):
    _name = 'encoach.vocab.item'
    _description = 'Training Vocabulary Item'
    _order = 'level,word'

    word = fields.Char('Word', required=True, index=True)
    meaning = fields.Text('Meaning', required=True)
    example_sentence = fields.Text('Example Sentence')
    level = fields.Selection(CEFR_LEVELS, string='CEFR Level', default='B1', required=True)
    part_of_speech = fields.Selection([
        ('noun', 'Noun'),
        ('verb', 'Verb'),
        ('adjective', 'Adjective'),
        ('adverb', 'Adverb'),
        ('phrase', 'Phrase'),
        ('other', 'Other'),
    ], string='Part of Speech', default='noun')
    category = fields.Char('Category', default='general',
                           help='Tag such as "academic", "business", "daily".')
    active = fields.Boolean('Active', default=True)

    progress_ids = fields.One2many('encoach.vocab.progress', 'vocab_id', 'Progress')

    completion_count = fields.Integer('Completions', compute='_compute_stats')
    learners_count = fields.Integer('Learners', compute='_compute_stats')

    @api.depends('progress_ids.completed')
    def _compute_stats(self):
        for rec in self:
            rec.learners_count = len(rec.progress_ids)
            rec.completion_count = len(rec.progress_ids.filtered(lambda p: p.completed))

    @api.constrains('word')
    def _check_word_unique(self):
        for rec in self:
            if not rec.word:
                continue
            dup = self.sudo().search([
                ('id', '!=', rec.id),
                ('word', '=ilike', rec.word.strip()),
            ], limit=1)
            if dup:
                from odoo.exceptions import ValidationError
                raise ValidationError(f"Word '{rec.word}' already exists.")


class EncoachVocabProgress(models.Model):
    _name = 'encoach.vocab.progress'
    _description = 'Vocabulary Progress'
    _order = 'last_reviewed desc'

    user_id = fields.Many2one('res.users', required=True,
                              default=lambda self: self.env.user.id,
                              ondelete='cascade')
    vocab_id = fields.Many2one('encoach.vocab.item', required=True, ondelete='cascade')
    completed = fields.Boolean('Completed', default=False)
    mastery = fields.Selection([
        ('learning', 'Learning'),
        ('familiar', 'Familiar'),
        ('mastered', 'Mastered'),
    ], default='learning')
    last_reviewed = fields.Datetime('Last Reviewed')
    review_count = fields.Integer('Review Count', default=0)

    @api.constrains('user_id', 'vocab_id')
    def _check_unique_user_vocab(self):
        for rec in self:
            dup = self.sudo().search([
                ('id', '!=', rec.id),
                ('user_id', '=', rec.user_id.id),
                ('vocab_id', '=', rec.vocab_id.id),
            ], limit=1)
            if dup:
                from odoo.exceptions import ValidationError
                raise ValidationError("Progress already exists for this user + vocabulary item.")


class EncoachGrammarRule(models.Model):
    _name = 'encoach.grammar.rule'
    _description = 'Training Grammar Rule'
    _order = 'level,name'

    name = fields.Char('Rule', required=True, index=True)
    description = fields.Text('Description', required=True)
    example = fields.Text('Example')
    level = fields.Selection(CEFR_LEVELS, string='CEFR Level', default='B1', required=True)
    category = fields.Char('Category', default='general',
                           help='Tag such as "tenses", "modals", "clauses".')
    active = fields.Boolean('Active', default=True)

    progress_ids = fields.One2many('encoach.grammar.progress', 'rule_id', 'Progress')

    completion_count = fields.Integer('Completions', compute='_compute_stats')
    learners_count = fields.Integer('Learners', compute='_compute_stats')

    @api.depends('progress_ids.completed')
    def _compute_stats(self):
        for rec in self:
            rec.learners_count = len(rec.progress_ids)
            rec.completion_count = len(rec.progress_ids.filtered(lambda p: p.completed))

    @api.constrains('name')
    def _check_rule_name_unique(self):
        for rec in self:
            if not rec.name:
                continue
            dup = self.sudo().search([
                ('id', '!=', rec.id),
                ('name', '=ilike', rec.name.strip()),
            ], limit=1)
            if dup:
                from odoo.exceptions import ValidationError
                raise ValidationError(f"Grammar rule '{rec.name}' already exists.")


class EncoachGrammarProgress(models.Model):
    _name = 'encoach.grammar.progress'
    _description = 'Grammar Rule Progress'
    _order = 'last_reviewed desc'

    user_id = fields.Many2one('res.users', required=True,
                              default=lambda self: self.env.user.id,
                              ondelete='cascade')
    rule_id = fields.Many2one('encoach.grammar.rule', required=True, ondelete='cascade')
    completed = fields.Boolean('Completed', default=False)
    last_reviewed = fields.Datetime('Last Reviewed')
    review_count = fields.Integer('Review Count', default=0)

    @api.constrains('user_id', 'rule_id')
    def _check_unique_user_rule(self):
        for rec in self:
            dup = self.sudo().search([
                ('id', '!=', rec.id),
                ('user_id', '=', rec.user_id.id),
                ('rule_id', '=', rec.rule_id.id),
            ], limit=1)
            if dup:
                from odoo.exceptions import ValidationError
                raise ValidationError("Progress already exists for this user + grammar rule.")
