import json
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__)


def _assignment_to_dict(rec):
    return {
        'id': rec.id,
        'title': rec.exam_id.title if rec.exam_id else f'Assignment #{rec.id}',
        'exam_id': rec.exam_id.id if rec.exam_id else None,
        'student_id': rec.student_id.id if rec.student_id else None,
        'student_name': rec.student_id.name if rec.student_id else None,
        'batch_id': rec.batch_id.id if rec.batch_id else None,
        'batch_name': rec.batch_id.name if rec.batch_id else None,
        'entity_name': rec.exam_id.entity_id.name if rec.exam_id and rec.exam_id.entity_id else None,
        'start_date': rec.access_start.isoformat() if rec.access_start else None,
        'end_date': rec.access_end.isoformat() if rec.access_end else None,
        'state': rec.status,
        'assignee_count': 1,
        'completed_count': 1 if rec.status == 'completed' else 0,
    }


class EncoachAssignmentController(http.Controller):

    @http.route('/api/assignments', type='http', auth='none',
                methods=['GET'], csrf=False)
    @jwt_required
    def list_assignments(self, **kw):
        try:
            Assignment = request.env['encoach.exam.assignment'].sudo()
            search = kw.get('search', '').strip()
            domain = []
            if search:
                domain = [('exam_id.title', 'ilike', search)]

            total = Assignment.search_count(domain)
            page, per_page, offset = _paginate(kw)
            records = Assignment.search(domain, limit=per_page, offset=offset,
                                        order='id desc')
            return _json_response({
                'items': [_assignment_to_dict(r) for r in records],
                'total': total,
                'page': page,
                'per_page': per_page,
            })
        except Exception as e:
            _logger.exception('assignments list failed')
            return _error_response(str(e), 500)

    @http.route('/api/assignments', type='http', auth='none',
                methods=['POST'], csrf=False)
    @jwt_required
    def create_assignment(self, **kw):
        try:
            body = _get_json_body()
            title = (body.get('title') or '').strip()
            if not title:
                return _error_response('title is required', 400)

            exam_id = body.get('exam_id')
            if not exam_id:
                Exam = request.env['encoach.exam.custom'].sudo()
                exam = Exam.create({
                    'title': title,
                    'teacher_id': request.env.user.id,
                    'status': 'draft',
                    'total_time_min': 0,
                })
                exam_id = exam.id

            vals = {
                'exam_id': exam_id,
                'student_id': body.get('student_id') or False,
                'batch_id': body.get('batch_id') or False,
                'status': 'assigned',
            }

            start_date = body.get('start_date')
            end_date = body.get('end_date')
            if start_date:
                vals['access_start'] = start_date
            if end_date:
                vals['access_end'] = end_date

            rec = request.env['encoach.exam.assignment'].sudo().create(vals)
            return _json_response(_assignment_to_dict(rec), 201)
        except Exception as e:
            _logger.exception('assignment create failed')
            return _error_response(str(e), 500)

    @http.route('/api/assignments/<int:assignment_id>', type='http',
                auth='none', methods=['GET'], csrf=False)
    @jwt_required
    def get_assignment(self, assignment_id, **kw):
        try:
            rec = request.env['encoach.exam.assignment'].sudo().browse(assignment_id)
            if not rec.exists():
                return _error_response('Assignment not found', 404)
            return _json_response(_assignment_to_dict(rec))
        except Exception as e:
            _logger.exception('assignment get failed')
            return _error_response(str(e), 500)
