# Task Team Connector — OAuth2 Authorization Server bridge
import json
import logging
import urllib.parse

from odoo import http
from odoo.http import request

_logger = logging.getLogger(__name__)


class TaskTeamOAuthController(http.Controller):
    """
    Implements a minimal OAuth2 Authorization Code flow so that
    Task Team can authenticate users via their Odoo credentials.

    Flow:
      1. Task Team redirects browser to  GET /task_team/oauth/authorize
      2. Odoo shows a consent page (user must be logged in)
      3. User approves → Odoo redirects to redirect_uri?code=XXX&state=YYY
      4. Task Team backend calls  POST /task_team/oauth/token  to exchange code
      5. Response includes Odoo user info + tt_user_id
      6. Task Team uses tt_user_id / email to issue its own JWT
    """

    # ------------------------------------------------------------------
    # Authorization endpoint
    # ------------------------------------------------------------------

    @http.route(
        '/task_team/oauth/authorize',
        type='http',
        auth='user',
        methods=['GET', 'POST'],
        website=False,
    )
    def authorize(
        self,
        client_id=None,
        redirect_uri=None,
        response_type=None,
        state=None,
        **kwargs,
    ):
        ICP = request.env['ir.config_parameter'].sudo()
        expected_client_id = ICP.get_param('task_team_connector.oauth_client_id', '')

        def _error(msg, status=400):
            return request.make_response(
                json.dumps({'error': msg}),
                headers=[('Content-Type', 'application/json')],
                status=status,
            )

        if not client_id or client_id != expected_client_id:
            return _error('invalid_client')
        if response_type != 'code':
            return _error('unsupported_response_type')

        if request.httprequest.method == 'POST':
            # User approved consent → issue code
            code = request.env['task.team.oauth.code'].sudo().generate_code(
                user_id=request.env.user.id,
                client_id=client_id,
                redirect_uri=redirect_uri or '',
                state=state or '',
            )
            params = urllib.parse.urlencode(
                {'code': code, 'state': state or ''}, quote_via=urllib.parse.quote
            )
            return request.redirect(f'{redirect_uri}?{params}')

        # GET → render consent form
        return request.render(
            'task_team_connector.oauth_consent_template',
            {
                'client_id': client_id,
                'redirect_uri': redirect_uri,
                'state': state,
                'user_name': request.env.user.name,
            },
        )

    # ------------------------------------------------------------------
    # Token endpoint
    # ------------------------------------------------------------------

    @http.route(
        '/task_team/oauth/token',
        type='json',
        auth='public',
        methods=['POST'],
        csrf=False,
    )
    def token(self, **kwargs):
        data = request.get_json_data()
        grant_type = data.get('grant_type')
        client_id = data.get('client_id')
        client_secret = data.get('client_secret')
        code = data.get('code')

        ICP = request.env['ir.config_parameter'].sudo()
        expected_client_id = ICP.get_param('task_team_connector.oauth_client_id', '')
        expected_secret = ICP.get_param('task_team_connector.oauth_client_secret', '')

        if client_id != expected_client_id or client_secret != expected_secret:
            return {'error': 'invalid_client'}
        if grant_type != 'authorization_code':
            return {'error': 'unsupported_grant_type'}
        if not code:
            return {'error': 'invalid_request'}

        code_record = (
            request.env['task.team.oauth.code'].sudo().validate_and_consume(code, client_id)
        )
        if not code_record:
            return {'error': 'invalid_grant'}

        user = code_record.user_id
        tt_user_id = user._tt_get_or_create_user()

        return {
            'token_type': 'bearer',
            'odoo_user_id': user.id,
            'odoo_email': user.email,
            'odoo_name': user.name,
            'tt_user_id': tt_user_id,
        }

    # ------------------------------------------------------------------
    # Userinfo endpoint
    # ------------------------------------------------------------------

    @http.route('/task_team/oauth/userinfo', type='json', auth='user', methods=['GET'])
    def userinfo(self, **kwargs):
        user = request.env.user
        return {
            'sub': str(user.id),
            'email': user.email,
            'name': user.name,
            'tt_user_id': user.tt_user_id,
        }
