import json
import logging
from datetime import datetime

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 _cr():
    return request.env.cr


def _user_name(cr, user_id):
    if not user_id:
        return ''
    cr.execute(
        "SELECT rp.name FROM res_users ru "
        "JOIN res_partner rp ON rp.id = ru.partner_id "
        "WHERE ru.id = %s", (user_id,))
    row = cr.fetchone()
    return row[0] if row else ''


class ApprovalWorkflowController(http.Controller):

    @http.route('/api/approval-workflows', type='http', auth='none',
                methods=['GET'], csrf=False)
    @jwt_required
    def list_workflows(self, **kw):
        try:
            cr = _cr()
            cr.execute(
                "SELECT id, name, type, allow_bypass, entity_id, create_date "
                "FROM encoach_approval_workflow ORDER BY create_date DESC")
            workflows = cr.fetchall()

            items = []
            for wf_id, name, wtype, bypass, entity_id, created in workflows:
                cr.execute(
                    "SELECT id, sequence, approver_id, status, comment, "
                    "auto_escalate, max_days, acted_at "
                    "FROM encoach_approval_stage WHERE workflow_id = %s "
                    "ORDER BY sequence ASC", (wf_id,))
                steps = []
                for sid, seq, approver_id, status, comment, escalate, max_d, acted in cr.fetchall():
                    steps.append({
                        'id': sid,
                        'sequence': seq,
                        'approver_id': approver_id,
                        'approver_name': _user_name(cr, approver_id),
                        'status': status or 'pending',
                        'comment': comment or '',
                        'auto_escalate': bool(escalate),
                        'max_days': max_d or 0,
                        'acted_at': acted.isoformat() if acted else None,
                    })

                entity_name = None
                if entity_id:
                    cr.execute("SELECT name FROM encoach_entity WHERE id=%s", (entity_id,))
                    row = cr.fetchone()
                    entity_name = row[0] if row else None

                items.append({
                    'id': wf_id,
                    'name': name,
                    'type': wtype or '',
                    'entity_id': entity_id,
                    'entity_name': entity_name,
                    'allow_bypass': bool(bypass),
                    'steps': steps,
                    'created': created.strftime('%Y-%m-%d') if created else '',
                })

            return _json_response({'items': items, 'total': len(items)})
        except Exception as e:
            _logger.exception('list workflows failed')
            return _json_response({'error': str(e)}, 500)

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

            cr = _cr()
            now = datetime.now()
            uid = request.env.uid

            cr.execute(
                "INSERT INTO encoach_approval_workflow "
                "(name, type, allow_bypass, create_uid, write_uid, create_date, write_date) "
                "VALUES (%s, %s, %s, %s, %s, %s, %s) RETURNING id",
                (name, body.get('type', 'custom'), body.get('allow_bypass', False),
                 uid, uid, now, now))
            wf_id = cr.fetchone()[0]

            for i, step in enumerate(body.get('steps', [])):
                approver_id = step.get('approver_id')
                if approver_id:
                    cr.execute(
                        "INSERT INTO encoach_approval_stage "
                        "(workflow_id, sequence, approver_id, status, auto_escalate, max_days, "
                        "create_uid, write_uid, create_date, write_date) "
                        "VALUES (%s, %s, %s, 'pending', %s, %s, %s, %s, %s, %s)",
                        (wf_id, (i + 1) * 10, int(approver_id),
                         step.get('auto_escalate', True), step.get('max_days', 3),
                         uid, uid, now, now))

            cr.execute("SELECT id, name, type FROM encoach_approval_workflow WHERE id=%s", (wf_id,))
            row = cr.fetchone()
            return _json_response({'id': row[0], 'name': row[1], 'type': row[2]}, 201)
        except Exception as e:
            _logger.exception('create workflow failed')
            return _json_response({'error': str(e)}, 500)

    @http.route('/api/approval-workflows/<int:wf_id>', type='http', auth='none',
                methods=['DELETE'], csrf=False)
    @jwt_required
    def delete_workflow(self, wf_id, **kw):
        try:
            cr = _cr()
            cr.execute("DELETE FROM encoach_approval_request WHERE workflow_id=%s", (wf_id,))
            cr.execute("DELETE FROM encoach_approval_stage WHERE workflow_id=%s", (wf_id,))
            cr.execute("DELETE FROM encoach_approval_workflow WHERE id=%s", (wf_id,))
            return _json_response({'success': True})
        except Exception as e:
            _logger.exception('delete workflow failed')
            return _json_response({'error': str(e)}, 500)

    # ── Approval Requests ──

    @http.route('/api/approval-requests', type='http', auth='none',
                methods=['GET'], csrf=False)
    @jwt_required
    def list_requests(self, **kw):
        try:
            cr = _cr()
            state_filter = kw.get('state')
            where = ""
            params = []
            if state_filter:
                where = "WHERE ar.state = %s"
                params.append(state_filter)

            cr.execute(f"""
                SELECT ar.id, ar.workflow_id, aw.name as wf_name,
                       ar.res_model, ar.res_id, ar.state,
                       ar.requester_id, ar.current_stage_id,
                       ar.bypass_reason, ar.created_at
                FROM encoach_approval_request ar
                LEFT JOIN encoach_approval_workflow aw ON aw.id = ar.workflow_id
                {where}
                ORDER BY ar.created_at DESC NULLS LAST
            """, params)

            items = []
            for row in cr.fetchall():
                rid, wf_id, wf_name, model, res_id, state, req_id, stage_id, bypass, created = row
                stage_seq = None
                if stage_id:
                    cr.execute("SELECT sequence FROM encoach_approval_stage WHERE id=%s", (stage_id,))
                    s = cr.fetchone()
                    stage_seq = s[0] if s else None

                items.append({
                    'id': rid,
                    'workflow_id': wf_id,
                    'workflow_name': wf_name or '',
                    'res_model': model or '',
                    'res_id': res_id or 0,
                    'state': state or 'draft',
                    'requester_id': req_id,
                    'requester_name': _user_name(cr, req_id),
                    'current_stage_id': stage_id,
                    'current_stage_sequence': stage_seq,
                    'bypass_reason': bypass or '',
                    'created_at': created.isoformat() if created else None,
                })

            return _json_response({'items': items, 'total': len(items)})
        except Exception as e:
            _logger.exception('list requests failed')
            return _json_response({'error': str(e)}, 500)

    @http.route('/api/approval-requests/<int:req_id>/approve', type='http',
                auth='none', methods=['POST'], csrf=False)
    @jwt_required
    def approve_request(self, req_id, **kw):
        try:
            cr = _cr()
            body = _get_json_body()
            now = datetime.now()

            cr.execute(
                "SELECT workflow_id, current_stage_id FROM encoach_approval_request WHERE id=%s",
                (req_id,))
            row = cr.fetchone()
            if not row:
                return _error_response('Request not found', 404)
            wf_id, stage_id = row

            if stage_id:
                cr.execute(
                    "UPDATE encoach_approval_stage SET status='approved', comment=%s, acted_at=%s "
                    "WHERE id=%s", (body.get('comment', ''), now, stage_id))

            cr.execute(
                "SELECT id FROM encoach_approval_stage WHERE workflow_id=%s ORDER BY sequence ASC",
                (wf_id,))
            all_stages = [r[0] for r in cr.fetchall()]

            try:
                idx = all_stages.index(stage_id)
            except ValueError:
                idx = -1

            if idx + 1 < len(all_stages):
                cr.execute(
                    "UPDATE encoach_approval_request SET current_stage_id=%s, state='in_progress' "
                    "WHERE id=%s", (all_stages[idx + 1], req_id))
            else:
                cr.execute(
                    "UPDATE encoach_approval_request SET state='approved' WHERE id=%s", (req_id,))

            return _json_response({'success': True, 'id': req_id})
        except Exception as e:
            _logger.exception('approve request failed')
            return _json_response({'error': str(e)}, 500)

    @http.route('/api/approval-requests/<int:req_id>/reject', type='http',
                auth='none', methods=['POST'], csrf=False)
    @jwt_required
    def reject_request(self, req_id, **kw):
        try:
            cr = _cr()
            body = _get_json_body()
            now = datetime.now()

            cr.execute("SELECT current_stage_id FROM encoach_approval_request WHERE id=%s", (req_id,))
            row = cr.fetchone()
            if not row:
                return _error_response('Request not found', 404)

            stage_id = row[0]
            if stage_id:
                cr.execute(
                    "UPDATE encoach_approval_stage SET status='rejected', comment=%s, acted_at=%s "
                    "WHERE id=%s", (body.get('comment', ''), now, stage_id))

            cr.execute(
                "UPDATE encoach_approval_request SET state='rejected' WHERE id=%s", (req_id,))
            return _json_response({'success': True, 'id': req_id})
        except Exception as e:
            _logger.exception('reject request failed')
            return _json_response({'error': str(e)}, 500)

    # ── Users for assignee selection ──

    @http.route('/api/approval-users', type='http', auth='none',
                methods=['GET'], csrf=False)
    @jwt_required
    def list_users(self, **kw):
        try:
            cr = _cr()
            cr.execute(
                "SELECT ru.id, rp.name, ru.login "
                "FROM res_users ru JOIN res_partner rp ON rp.id = ru.partner_id "
                "WHERE ru.active = true AND ru.id > 1 "
                "ORDER BY rp.name LIMIT 100")
            items = [{'id': r[0], 'name': r[1], 'login': r[2]} for r in cr.fetchall()]
            return _json_response({'items': items})
        except Exception as e:
            _logger.exception('list users failed')
            return _json_response({'error': str(e)}, 500)
