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 _ser_ticket(t):
    return {
        'id': t.id,
        'subject': t.subject or '',
        'description': t.description or '',
        'type': t.type or 'support',
        'status': t.status or 'open',
        'source': t.source or 'platform',
        'page_context': t.page_context or '',
        'reporter_id': t.reporter_id.id if t.reporter_id else None,
        'reporter_name': t.reporter_id.name if t.reporter_id else '',
        'assignee_id': t.assignee_id.id if t.assignee_id else None,
        'assignee_name': t.assignee_id.name if t.assignee_id else '',
        'entity_id': t.entity_id.id if t.entity_id else None,
        'entity_name': t.entity_id.name if t.entity_id else '',
        'created_at': t.create_date.isoformat() if t.create_date else '',
        'resolved_at': t.resolved_at.isoformat() if t.resolved_at else '',
    }


class TicketsController(http.Controller):

    @http.route('/api/tickets', type='http', auth='public', methods=['GET'], csrf=False)
    @jwt_required
    def list_tickets(self, **kw):
        try:
            Ticket = request.env['encoach.ticket'].sudo()
            domain = []
            status = kw.get('status')
            if status and status != 'all':
                domain.append(('status', '=', status))
            t = kw.get('type')
            if t and t != 'all':
                domain.append(('type', '=', t))
            src = kw.get('source')
            if src and src != 'all':
                domain.append(('source', '=', src))
            assignee = kw.get('assignee_id')
            if assignee:
                try:
                    domain.append(('assignee_id', '=', int(assignee)))
                except (TypeError, ValueError):
                    pass
            search = kw.get('search') or kw.get('q')
            if search:
                domain.append('|')
                domain.append(('subject', 'ilike', search))
                domain.append(('description', 'ilike', search))

            try:
                size = min(int(kw.get('size') or 50), 200)
            except (TypeError, ValueError):
                size = 50
            try:
                page = max(int(kw.get('page') or 1), 1)
            except (TypeError, ValueError):
                page = 1

            total = Ticket.search_count(domain)
            recs = Ticket.search(domain, limit=size, offset=(page - 1) * size)
            items = [_ser_ticket(t) for t in recs]
            return _json_response({
                'data': items,
                'items': items,
                'total': total,
                'page': page,
                'size': size,
            })
        except Exception as e:
            _logger.exception('list_tickets')
            return _error_response(str(e), 500)

    @http.route('/api/tickets', type='http', auth='public', methods=['POST'], csrf=False)
    @jwt_required
    def create_ticket(self, **kw):
        try:
            body = _get_json_body()
            if not body.get('subject'):
                return _error_response('subject is required', 400)
            vals = {
                'subject': body['subject'],
                'description': body.get('description') or '',
                'type': body.get('type') or 'support',
                'status': body.get('status') or 'open',
                'source': body.get('source') or 'platform',
                'page_context': body.get('page_context') or '',
            }
            if body.get('assignee_id'):
                vals['assignee_id'] = int(body['assignee_id'])
            if body.get('entity_id'):
                vals['entity_id'] = int(body['entity_id'])
            # reporter defaults to current user via the model default.
            rec = request.env['encoach.ticket'].sudo().create(vals)
            return _json_response(_ser_ticket(rec))
        except Exception as e:
            _logger.exception('create_ticket')
            return _error_response(str(e), 500)

    @http.route('/api/tickets/<int:tid>', type='http', auth='public',
                methods=['GET'], csrf=False)
    @jwt_required
    def get_ticket(self, tid, **kw):
        try:
            rec = request.env['encoach.ticket'].sudo().browse(tid)
            if not rec.exists():
                return _error_response('Not found', 404)
            return _json_response(_ser_ticket(rec))
        except Exception as e:
            _logger.exception('get_ticket')
            return _error_response(str(e), 500)

    @http.route('/api/tickets/<int:tid>', type='http', auth='public',
                methods=['PATCH', 'PUT'], csrf=False)
    @jwt_required
    def update_ticket(self, tid, **kw):
        try:
            from odoo import fields as odoo_fields
            body = _get_json_body()
            rec = request.env['encoach.ticket'].sudo().browse(tid)
            if not rec.exists():
                return _error_response('Not found', 404)
            vals = {}
            for k in ('subject', 'description', 'type', 'status', 'source', 'page_context'):
                if k in body:
                    vals[k] = body[k]
            if 'assignee_id' in body:
                vals['assignee_id'] = int(body['assignee_id']) if body['assignee_id'] else False
            if 'entity_id' in body:
                vals['entity_id'] = int(body['entity_id']) if body['entity_id'] else False
            # Auto-stamp resolved_at when transitioning to resolved/closed.
            if vals.get('status') in ('resolved', 'closed') and not rec.resolved_at:
                vals['resolved_at'] = odoo_fields.Datetime.now()
            if vals:
                rec.write(vals)
            return _json_response(_ser_ticket(rec))
        except Exception as e:
            _logger.exception('update_ticket')
            return _error_response(str(e), 500)

    @http.route('/api/tickets/<int:tid>', type='http', auth='public',
                methods=['DELETE'], csrf=False)
    @jwt_required
    def delete_ticket(self, tid, **kw):
        try:
            rec = request.env['encoach.ticket'].sudo().browse(tid)
            if rec.exists():
                rec.unlink()
            return _json_response({'success': True})
        except Exception as e:
            _logger.exception('delete_ticket')
            return _error_response(str(e), 500)

    @http.route('/api/tickets/assignedToUser', type='http', auth='public',
                methods=['GET'], csrf=False)
    @jwt_required
    def assigned_to_user(self, **kw):
        try:
            uid = request.env.user.id
            recs = request.env['encoach.ticket'].sudo().search([
                ('assignee_id', '=', uid),
            ], limit=100)
            items = [_ser_ticket(t) for t in recs]
            return _json_response({'data': items, 'items': items, 'total': len(items)})
        except Exception as e:
            _logger.exception('assigned_to_user')
            return _error_response(str(e), 500)
