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 _entity_scope():
    """Same convention as ``encoach_lms_api.controllers.lms_core._entity_scope``."""
    user = request.env.user.sudo()
    ids = user.entity_ids.ids if hasattr(user, 'entity_ids') else []
    if ids:
        return ids, False
    is_super = bool(
        user.id == 1 or user.has_group('base.group_system')
    )
    return ids, is_super


def _ensure_entity_access(entity_id):
    if not entity_id:
        raise PermissionError('entity_id is required')
    ids, is_super = _entity_scope()
    if is_super:
        return int(entity_id)
    if not ids:
        raise PermissionError('User is not linked to any entity')
    if int(entity_id) not in ids:
        raise PermissionError('Entity access denied')
    return int(entity_id)


def _default_entity_id_from_scope():
    ids, is_super = _entity_scope()
    if ids:
        return ids[0]
    if is_super:
        return False
    raise PermissionError('User is not linked to any entity')


def _scoped_entity_domain(base_domain=None):
    domain = list(base_domain or [])
    ids, is_super = _entity_scope()
    if is_super:
        return domain
    if not ids:
        return domain + [('id', '=', 0)]
    return domain + [('entity_id', 'in', ids)]


def _ser_branch(rec):
    return {
        'id': rec.id,
        'name': rec.name or '',
        'code': rec.code or '',
        'active': bool(rec.active),
        'notes': rec.notes or '',
        'entity_id': rec.entity_id.id if rec.entity_id else None,
        'entity_name': rec.entity_id.name if rec.entity_id else '',
        'course_count': rec.course_count or 0,
        'batch_count': rec.batch_count or 0,
        'student_count': rec.student_count or 0,
        'teacher_count': rec.teacher_count or 0,
    }


class LmsBranchController(http.Controller):
    @http.route('/api/branches', type='http', auth='public', methods=['GET'], csrf=False)
    @jwt_required
    def list_branches(self, **kw):
        try:
            Branch = request.env['encoach.lms.branch'].sudo()
            domain = _scoped_entity_domain([])
            if kw.get('search'):
                q = kw['search']
                domain += ['|', ('name', 'ilike', q), ('code', 'ilike', q)]
            if kw.get('active') in ('true', 'false', '1', '0'):
                domain.append(('active', '=', kw.get('active') in ('true', '1')))
            if kw.get('entity_id'):
                domain.append(('entity_id', '=', _ensure_entity_access(int(kw['entity_id']))))
            offset, limit, page = _paginate(kw)
            total = Branch.search_count(domain)
            recs = Branch.search(domain, offset=offset, limit=limit, order='name asc, id asc')
            items = [_ser_branch(r) for r in recs]
            return _json_response({'items': items, 'data': items, 'total': total, 'page': page, 'size': limit})
        except Exception as exc:
            _logger.exception('list_branches failed')
            return _error_response(str(exc), 403 if isinstance(exc, PermissionError) else 500)

    @http.route('/api/branches/<int:branch_id>', type='http', auth='public', methods=['GET'], csrf=False)
    @jwt_required
    def get_branch(self, branch_id, **kw):
        try:
            rec = request.env['encoach.lms.branch'].sudo().browse(branch_id)
            if not rec.exists():
                return _error_response('Not found', 404)
            _ensure_entity_access(rec.entity_id.id)
            return _json_response({'data': _ser_branch(rec)})
        except Exception as exc:
            _logger.exception('get_branch failed')
            return _error_response(str(exc), 403 if isinstance(exc, PermissionError) else 500)

    @http.route('/api/branches', type='http', auth='public', methods=['POST'], csrf=False)
    @jwt_required
    def create_branch(self, **kw):
        try:
            body = _get_json_body()
            name = (body.get('name') or '').strip()
            if not name:
                return _error_response('name is required', 400)
            requested_entity = body.get('entity_id')
            if requested_entity:
                entity_id = _ensure_entity_access(int(requested_entity))
            else:
                entity_id = _default_entity_id_from_scope()
            vals = {
                'name': name,
                'entity_id': entity_id,
                'code': (body.get('code') or '').strip() or False,
                'notes': (body.get('notes') or '').strip(),
            }
            if 'active' in body:
                vals['active'] = bool(body.get('active'))
            rec = request.env['encoach.lms.branch'].sudo().create(vals)
            return _json_response({'data': _ser_branch(rec)})
        except Exception as exc:
            _logger.exception('create_branch failed')
            return _error_response(str(exc), 403 if isinstance(exc, PermissionError) else 500)

    @http.route('/api/branches/<int:branch_id>', type='http', auth='public', methods=['PATCH', 'PUT'], csrf=False)
    @jwt_required
    def update_branch(self, branch_id, **kw):
        try:
            rec = request.env['encoach.lms.branch'].sudo().browse(branch_id)
            if not rec.exists():
                return _error_response('Not found', 404)
            _ensure_entity_access(rec.entity_id.id)
            body = _get_json_body()
            vals = {}
            if 'name' in body:
                vals['name'] = (body.get('name') or '').strip()
            if 'code' in body:
                vals['code'] = (body.get('code') or '').strip() or False
            if 'notes' in body:
                vals['notes'] = (body.get('notes') or '').strip()
            if 'active' in body:
                vals['active'] = bool(body.get('active'))
            if 'entity_id' in body and body.get('entity_id'):
                vals['entity_id'] = _ensure_entity_access(int(body.get('entity_id')))
            if vals:
                rec.write(vals)
            return _json_response({'data': _ser_branch(rec)})
        except Exception as exc:
            _logger.exception('update_branch failed')
            return _error_response(str(exc), 403 if isinstance(exc, PermissionError) else 500)

    @http.route('/api/branches/<int:branch_id>', type='http', auth='public', methods=['DELETE'], csrf=False)
    @jwt_required
    def delete_branch(self, branch_id, **kw):
        try:
            rec = request.env['encoach.lms.branch'].sudo().browse(branch_id)
            if rec.exists():
                _ensure_entity_access(rec.entity_id.id)
                rec.unlink()
            return _json_response({'success': True})
        except Exception as exc:
            _logger.exception('delete_branch failed')
            return _error_response(str(exc), 403 if isinstance(exc, PermissionError) else 500)

