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

ENTITY_MODEL = 'encoach.entity'


def _entity_to_dict(entity):
    d = entity.to_api_dict() if hasattr(entity, 'to_api_dict') else {
        'id': entity.id,
        'name': entity.name,
        'code': getattr(entity, 'code', '') or '',
        'type': getattr(entity, 'type', '') or '',
        'active': entity.active if hasattr(entity, 'active') else True,
        'user_count': getattr(entity, 'user_count', 0) or 0,
    }
    d['role_count'] = len(entity.role_ids) if hasattr(entity, 'role_ids') else 0
    return d


def _role_to_dict(role):
    return {
        'id': role.id,
        'name': role.name,
        'code': getattr(role, 'code', '') or '',
        'entity_id': role.entity_id.id if hasattr(role, 'entity_id') and role.entity_id else None,
        'permission_ids': role.permission_ids.ids if hasattr(role, 'permission_ids') else [],
        'user_count': len(role.user_ids) if hasattr(role, 'user_ids') else 0,
    }


class EntityController(http.Controller):

    @http.route('/api/entities', type='http', auth='public',
                methods=['GET'], csrf=False)
    @jwt_required
    def list_entities(self, **kw):
        try:
            M = request.env[ENTITY_MODEL].sudo()
            domain = []
            if kw.get('search'):
                domain.append(('name', 'ilike', kw['search']))
            if kw.get('type'):
                domain.append(('type', '=', kw['type']))
            recs = M.search(domain, order='name')
            items = [_entity_to_dict(r) for r in recs]
            return _json_response({
                'data': items,
                'items': items,
                'total': len(items),
            })
        except Exception as e:
            _logger.exception('list entities failed')
            return _error_response(str(e), 500)

    @http.route('/api/entities/<int:entity_id>', type='http', auth='public',
                methods=['GET'], csrf=False)
    @jwt_required
    def get_entity(self, entity_id, **kw):
        try:
            entity = request.env[ENTITY_MODEL].sudo().browse(entity_id)
            if not entity.exists():
                return _error_response('Entity not found', 404)
            return _json_response({'data': _entity_to_dict(entity)})
        except Exception as e:
            return _error_response(str(e), 500)

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

        code = body.get('code', '').strip()
        if not code:
            code = name.upper().replace(' ', '_')[:20]

        vals = {'name': name, 'code': code}
        for field in ('type', 'primary_color', 'secondary_color',
                      'background_color', 'login_title',
                      'login_description', 'results_release_mode'):
            if field in body:
                vals[field] = body[field]

        try:
            entity = request.env[ENTITY_MODEL].sudo().create(vals)
            return _json_response({'data': _entity_to_dict(entity)}, 201)
        except Exception as e:
            _logger.exception('Error creating entity')
            msg = str(e)
            if 'unique' in msg.lower() or 'duplicate' in msg.lower():
                return _error_response(
                    f'An entity with code "{code}" already exists', 409)
            return _error_response(msg, 500)

    @http.route('/api/entities/<int:entity_id>', type='http', auth='public',
                methods=['PATCH', 'PUT'], csrf=False)
    @jwt_required
    def update_entity(self, entity_id, **kw):
        body = _get_json_body()
        try:
            entity = request.env[ENTITY_MODEL].sudo().browse(entity_id)
            if not entity.exists():
                return _error_response('Entity not found', 404)

            vals = {}
            for field in ('name', 'code', 'type', 'primary_color',
                          'secondary_color', 'background_color',
                          'login_title', 'login_description',
                          'results_release_mode', 'active'):
                if field in body:
                    vals[field] = body[field]
            if vals:
                entity.write(vals)
            return _json_response({'data': _entity_to_dict(entity)})
        except Exception as e:
            return _error_response(str(e), 500)

    @http.route('/api/entities/<int:entity_id>', type='http', auth='public',
                methods=['DELETE'], csrf=False)
    @jwt_required
    def delete_entity(self, entity_id, **kw):
        try:
            entity = request.env[ENTITY_MODEL].sudo().browse(entity_id)
            if not entity.exists():
                return _error_response('Entity not found', 404)
            entity.sudo().unlink()
            return _json_response({'success': True})
        except Exception as e:
            msg = str(e)
            if 'foreign key' in msg.lower() or 'restrict' in msg.lower():
                return _error_response(
                    'Cannot delete: entity has linked users or roles', 409)
            return _error_response(msg, 500)

    @http.route('/api/entities/<int:entity_id>/roles', type='http',
                auth='public', methods=['GET'], csrf=False)
    @jwt_required
    def list_entity_roles(self, entity_id, **kw):
        try:
            roles = request.env['encoach.role'].sudo().search([
                ('entity_id', '=', entity_id)
            ])
            return _json_response({
                'data': [_role_to_dict(r) for r in roles],
                'total': len(roles),
            })
        except Exception as e:
            return _error_response(str(e), 500)

    @http.route('/api/entities/<int:entity_id>/roles', type='http',
                auth='public', methods=['POST'], csrf=False)
    @jwt_required
    def create_entity_role(self, entity_id, **kw):
        body = _get_json_body()
        name = body.get('name', '').strip()
        if not name:
            return _error_response('Role name is required', 400)
        vals = {'name': name, 'entity_id': entity_id}
        if body.get('permission_ids'):
            vals['permission_ids'] = [(6, 0, [int(p) for p in body['permission_ids']])]
        try:
            role = request.env['encoach.role'].sudo().create(vals)
            return _json_response({'data': _role_to_dict(role)}, 201)
        except Exception as e:
            return _error_response(str(e), 500)
