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,
)

_logger = logging.getLogger(__name__)


def _rubric_to_dict(rec):
    criteria_text = rec.criteria or ''
    criteria_count = 0
    if criteria_text:
        try:
            parsed = json.loads(criteria_text)
            if isinstance(parsed, list):
                criteria_count = len(parsed)
            elif isinstance(parsed, dict):
                criteria_count = len(parsed)
            else:
                criteria_count = len([l for l in criteria_text.split('\n') if l.strip()])
        except (json.JSONDecodeError, ValueError):
            criteria_count = len([l for l in criteria_text.split('\n') if l.strip()])

    levels = ['A1', 'A2', 'B1', 'B2', 'C1', 'C2']
    if rec.levels:
        try:
            parsed_levels = json.loads(rec.levels)
            if isinstance(parsed_levels, list) and parsed_levels:
                levels = parsed_levels
        except (json.JSONDecodeError, ValueError):
            pass

    return {
        'id': rec.id,
        'name': rec.name,
        'skill': rec.skill or '',
        'exam_type': rec.exam_type or '',
        'criteria': criteria_count or 1,
        'criteria_text': criteria_text,
        'levels': levels,
        'created': rec.create_date.strftime('%Y-%m-%d') if rec.create_date else '',
    }


class EncoachRubricController(http.Controller):

    @http.route('/api/rubrics', type='http', auth='none',
                methods=['GET'], csrf=False)
    @jwt_required
    def list_rubrics(self, **kw):
        try:
            Rubric = request.env['encoach.rubric'].sudo()
            limit = int(kw.get('limit', 50))
            offset = int(kw.get('offset', 0))
            records = Rubric.search([], limit=limit, offset=offset,
                                    order='create_date desc')
            total = Rubric.search_count([])
            return _json_response({
                'items': [_rubric_to_dict(r) for r in records],
                'total': total,
            })
        except Exception as e:
            _logger.exception('rubrics list failed')
            return _json_response({'error': str(e)}, 500)

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

            vals = {
                'name': name,
                'skill': body.get('skill', 'writing'),
                'criteria': body.get('criteria', ''),
                'exam_type': body.get('exam_type', 'academic'),
            }
            if 'levels' in body:
                vals['levels'] = json.dumps(body['levels'])
            rec = request.env['encoach.rubric'].sudo().create(vals)
            return _json_response(_rubric_to_dict(rec), 201)
        except Exception as e:
            _logger.exception('rubric create failed')
            return _json_response({'error': str(e)}, 500)

    @http.route('/api/rubrics/<int:rubric_id>', type='http', auth='none',
                methods=['PUT'], csrf=False)
    @jwt_required
    def update_rubric(self, rubric_id, **kw):
        try:
            rec = request.env['encoach.rubric'].sudo().browse(rubric_id)
            if not rec.exists():
                return _error_response('Rubric not found', 404)

            body = _get_json_body()
            vals = {}
            if 'name' in body:
                vals['name'] = body['name']
            if 'skill' in body:
                vals['skill'] = body['skill']
            if 'criteria' in body:
                vals['criteria'] = body['criteria']
            if 'exam_type' in body:
                vals['exam_type'] = body['exam_type']
            if 'levels' in body:
                vals['levels'] = json.dumps(body['levels'])

            if vals:
                rec.write(vals)

            return _json_response(_rubric_to_dict(rec))
        except Exception as e:
            _logger.exception('rubric update failed')
            return _json_response({'error': str(e)}, 500)

    @http.route('/api/rubrics/<int:rubric_id>', type='http', auth='none',
                methods=['DELETE'], csrf=False)
    @jwt_required
    def delete_rubric(self, rubric_id, **kw):
        try:
            rec = request.env['encoach.rubric'].sudo().browse(rubric_id)
            if not rec.exists():
                return _error_response('Rubric not found', 404)
            rec.unlink()
            return _json_response({'success': True})
        except Exception as e:
            _logger.exception('rubric delete failed')
            return _json_response({'error': str(e)}, 500)


def _group_to_dict(rec):
    return {
        'id': rec.id,
        'name': rec.name,
        'rubric_ids': rec.rubric_ids.ids,
        'rubric_names': [r.name for r in rec.rubric_ids],
        'created': rec.create_date.strftime('%Y-%m-%d') if rec.create_date else '',
    }


class EncoachRubricGroupController(http.Controller):

    @http.route('/api/rubric-groups', type='http', auth='none',
                methods=['GET'], csrf=False)
    @jwt_required
    def list_rubric_groups(self, **kw):
        try:
            Group = request.env['encoach.rubric.group'].sudo()
            limit = int(kw.get('limit', 50))
            offset = int(kw.get('offset', 0))
            records = Group.search([], limit=limit, offset=offset,
                                   order='create_date desc')
            total = Group.search_count([])
            return _json_response({
                'items': [_group_to_dict(r) for r in records],
                'total': total,
            })
        except Exception as e:
            _logger.exception('rubric-groups list failed')
            return _json_response({'error': str(e)}, 500)

    @http.route('/api/rubric-groups', type='http', auth='none',
                methods=['POST'], csrf=False)
    @jwt_required
    def create_rubric_group(self, **kw):
        try:
            body = _get_json_body()
            name = body.get('name', '').strip()
            if not name:
                return _error_response('name is required', 400)
            rubric_ids = body.get('rubric_ids', [])
            rec = request.env['encoach.rubric.group'].sudo().create({
                'name': name,
                'rubric_ids': [(6, 0, rubric_ids)],
            })
            return _json_response(_group_to_dict(rec), 201)
        except Exception as e:
            _logger.exception('rubric-group create failed')
            return _json_response({'error': str(e)}, 500)

    @http.route('/api/rubric-groups/<int:group_id>', type='http', auth='none',
                methods=['PUT'], csrf=False)
    @jwt_required
    def update_rubric_group(self, group_id, **kw):
        try:
            rec = request.env['encoach.rubric.group'].sudo().browse(group_id)
            if not rec.exists():
                return _error_response('Group not found', 404)
            body = _get_json_body()
            vals = {}
            if 'name' in body:
                vals['name'] = body['name']
            if 'rubric_ids' in body:
                vals['rubric_ids'] = [(6, 0, body['rubric_ids'])]
            if vals:
                rec.write(vals)
            return _json_response(_group_to_dict(rec))
        except Exception as e:
            _logger.exception('rubric-group update failed')
            return _json_response({'error': str(e)}, 500)

    @http.route('/api/rubric-groups/<int:group_id>', type='http', auth='none',
                methods=['DELETE'], csrf=False)
    @jwt_required
    def delete_rubric_group(self, group_id, **kw):
        try:
            rec = request.env['encoach.rubric.group'].sudo().browse(group_id)
            if not rec.exists():
                return _error_response('Group not found', 404)
            rec.unlink()
            return _json_response({'success': True})
        except Exception as e:
            _logger.exception('rubric-group delete failed')
            return _json_response({'error': str(e)}, 500)
