import logging
from odoo import http
from odoo.http import request
from odoo.addons.encoach_api.controllers.base import (
    jwt_required, _json_response, _error_response, _get_json_body, _paginate,
)

_logger = logging.getLogger(__name__)


class GradesController(http.Controller):

    # ── Grades (simple list) ─────────────────────────────────────────

    @http.route('/api/grades', type='http', auth='public', methods=['GET'], csrf=False)
    @jwt_required
    def list_grades(self, **kw):
        try:
            M = request.env['encoach.gradebook.line'].sudo()
            offset, limit, page = _paginate(kw)
            total = M.search_count([])
            recs = M.search([], offset=offset, limit=limit, order='id desc')
            data = []
            for r in recs:
                gb = r.gradebook_id
                data.append({
                    'id': r.id,
                    'course_id': gb.course_id.id if gb.course_id else 0,
                    'course_name': gb.course_id.name if gb.course_id else '',
                    'student_id': gb.student_id.id if gb.student_id else 0,
                    'student_name': gb.student_id.partner_id.name if gb.student_id and gb.student_id.partner_id else '',
                    'assignment_title': r.assignment_name or '',
                    'grade': r.marks,
                    'max_grade': 100,
                    'date': str(r.create_date.date()) if r.create_date else '',
                    'type': r.state or 'graded',
                })
            return _json_response({'data': data})
        except Exception as e:
            _logger.exception('list_grades')
            return _error_response(str(e), 500)

    # ── Gradebooks ───────────────────────────────────────────────────

    @http.route('/api/gradebooks', type='http', auth='public', methods=['GET'], csrf=False)
    @jwt_required
    def list_gradebooks(self, **kw):
        try:
            M = request.env['encoach.gradebook'].sudo()
            offset, limit, page = _paginate(kw)
            total = M.search_count([])
            recs = M.search([], offset=offset, limit=limit, order='id desc')
            items = [{
                'id': r.id,
                'student_id': r.student_id.id if r.student_id else 0,
                'student_name': r.student_id.partner_id.name if r.student_id and r.student_id.partner_id else '',
                'course_id': r.course_id.id if r.course_id else 0,
                'course_name': r.course_id.name if r.course_id else '',
                'academic_year_id': r.academic_year_id.id if r.academic_year_id else 0,
                'academic_year_name': r.academic_year_id.name if r.academic_year_id else '',
            } for r in recs]
            return _json_response({'items': items, 'data': items, 'total': total, 'page': page, 'size': limit})
        except Exception as e:
            return _error_response(str(e), 500)

    # ── Gradebook Lines ──────────────────────────────────────────────

    @http.route('/api/gradebook-lines', type='http', auth='public', methods=['GET'], csrf=False)
    @jwt_required
    def list_gradebook_lines(self, **kw):
        try:
            M = request.env['encoach.gradebook.line'].sudo()
            offset, limit, page = _paginate(kw)
            domain = []
            gb_id = kw.get('gradebook_id')
            if gb_id:
                try:
                    domain.append(('gradebook_id', '=', int(gb_id)))
                except Exception:
                    pass
            total = M.search_count(domain)
            recs = M.search(domain, offset=offset, limit=limit, order='id desc')
            items = [{
                'id': r.id,
                'gradebook_id': r.gradebook_id.id,
                'student_name': r.gradebook_id.student_id.partner_id.name if r.gradebook_id.student_id and r.gradebook_id.student_id.partner_id else '',
                'assignment_name': r.assignment_name or '',
                'marks': r.marks,
                'percentage': r.percentage,
                'state': r.state or 'draft',
            } for r in recs]
            return _json_response({'items': items, 'data': items, 'total': total, 'page': page, 'size': limit})
        except Exception as e:
            return _error_response(str(e), 500)

    # ── Grading Assignments (using openeducat grading.assignment) ────

    @http.route('/api/grading-assignments', type='http', auth='public', methods=['GET'], csrf=False)
    @jwt_required
    def list_grading_assignments(self, **kw):
        try:
            M = request.env['grading.assignment'].sudo()
            offset, limit, page = _paginate(kw)
            total = M.search_count([])
            recs = M.search([], offset=offset, limit=limit, order='id desc')
            items = [{
                'id': r.id,
                'sequence': getattr(r, 'sequence', '') or '',
                'name': r.name or '',
                'course_id': r.course_id.id if hasattr(r, 'course_id') and r.course_id else 0,
                'course_name': r.course_id.name if hasattr(r, 'course_id') and r.course_id else '',
                'subject_id': r.subject_id.id if hasattr(r, 'subject_id') and r.subject_id else 0,
                'subject_name': r.subject_id.name if hasattr(r, 'subject_id') and r.subject_id else '',
                'state': getattr(r, 'state', 'draft') or 'draft',
                'issued_date': str(r.issued_date) if hasattr(r, 'issued_date') and r.issued_date else '',
            } for r in recs]
            return _json_response({'items': items, 'data': items, 'total': total, 'page': page, 'size': limit})
        except Exception as e:
            return _error_response(str(e), 500)

    @http.route('/api/grading-assignments', type='http', auth='public', methods=['POST'], csrf=False)
    @jwt_required
    def create_grading_assignment(self, **kw):
        try:
            from odoo import fields as odoo_fields
            body = _get_json_body()

            # assignment_type is required on grading.assignment. Find or create a default.
            AType = request.env['grading.assignment.type'].sudo()
            atype_id = body.get('assignment_type') or body.get('assignment_type_id')
            if atype_id:
                atype_id = int(atype_id)
            else:
                atype = AType.search([('code', '=', 'DEFAULT')], limit=1)
                if not atype:
                    atype = AType.create({'name': 'Default', 'code': 'DEFAULT'})
                atype_id = atype.id

            # faculty_id is required. Prefer body, otherwise first available.
            Faculty = request.env['op.faculty'].sudo()
            faculty_id = body.get('faculty_id')
            if faculty_id:
                faculty_id = int(faculty_id)
            else:
                fac = Faculty.search([], limit=1)
                if fac:
                    faculty_id = fac.id

            if not faculty_id:
                return _error_response('A faculty is required but none exist in the system.', 400)

            vals = {
                'name': body.get('name') or 'Assignment',
                'issued_date': body.get('issued_date') or odoo_fields.Datetime.now(),
                'assignment_type': atype_id,
                'faculty_id': faculty_id,
            }
            if body.get('course_id'):
                vals['course_id'] = int(body['course_id'])
            if body.get('subject_id'):
                vals['subject_id'] = int(body['subject_id'])
            if body.get('point') is not None:
                vals['point'] = float(body['point'])
            rec = request.env['grading.assignment'].sudo().create(vals)
            return _json_response({'data': {'id': rec.id, 'name': rec.name}})
        except Exception as e:
            _logger.exception('create_grading_assignment')
            return _error_response(str(e), 500)

    @http.route('/api/grading-assignments/<int:gid>', type='http', auth='public', methods=['PATCH', 'PUT'], csrf=False)
    @jwt_required
    def update_grading_assignment(self, gid, **kw):
        try:
            rec = request.env['grading.assignment'].sudo().browse(gid)
            if not rec.exists():
                return _error_response('Not found', 404)
            body = _get_json_body()
            vals = {}
            for k in ('name', 'issued_date'):
                if k in body:
                    vals[k] = body[k]
            if 'course_id' in body:
                vals['course_id'] = int(body['course_id'])
            if 'subject_id' in body:
                vals['subject_id'] = int(body['subject_id'])
            if vals:
                rec.write(vals)
            return _json_response({'data': {'id': rec.id, 'name': rec.name}})
        except Exception as e:
            return _error_response(str(e), 500)

    @http.route('/api/grading-assignments/<int:gid>', type='http', auth='public', methods=['DELETE'], csrf=False)
    @jwt_required
    def delete_grading_assignment(self, gid, **kw):
        try:
            rec = request.env['grading.assignment'].sudo().browse(gid)
            if rec.exists():
                rec.unlink()
            return _json_response({'success': True})
        except Exception as e:
            return _error_response(str(e), 500)
