# Webhooks for external integrations.
from functools import partial
from typing import Any, Callable, Dict, Optional

from django.http import HttpRequest, HttpResponse

from zerver.decorator import api_key_only_webhook_view
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.webhooks.common import UnexpectedWebhookEventType, \
    check_send_webhook_message, get_http_headers_from_filename, \
    validate_extract_webhook_http_header
from zerver.models import UserProfile

TICKET_STARTED_TEMPLATE = """
{customer_name} submitted new ticket [#{number}: {title}]({app_url}):

``` quote
{summary}
```
""".strip()

TICKET_ASSIGNED_TEMPLATE = "[#{number}: {title}]({app_url}) ({state}) assigned to {assignee_info}."

AGENT_REPLIED_TEMPLATE = """
{actor} {action} [ticket #{number}]({app_ticket_url}):

``` quote
{plain_text_body}
```
""".strip()

def ticket_started_body(payload: Dict[str, Any]) -> str:
    return TICKET_STARTED_TEMPLATE.format(**payload)

def ticket_assigned_body(payload: Dict[str, Any]) -> Optional[str]:
    state = payload['state']
    kwargs = {
        'state': 'open' if state == 'opened' else state,
        'number': payload['number'],
        'title': payload['title'],
        'app_url': payload['app_url']
    }

    assignee = payload['assignee']
    assigned_group = payload['assigned_group']

    if assignee or assigned_group:
        if assignee and assigned_group:
            kwargs['assignee_info'] = '{assignee} from {assigned_group}'.format(**payload)
        elif assignee:
            kwargs['assignee_info'] = '{assignee}'.format(**payload)
        elif assigned_group:
            kwargs['assignee_info'] = '{assigned_group}'.format(**payload)

        return TICKET_ASSIGNED_TEMPLATE.format(**kwargs)
    else:
        return None

def replied_body(payload: Dict[str, Any], actor: str, action: str) -> str:
    actor_url = "http://api.groovehq.com/v1/{}/".format(actor + 's')
    actor = payload['links']['author']['href'].split(actor_url)[1]
    number = payload['links']['ticket']['href'].split("http://api.groovehq.com/v1/tickets/")[1]

    body = AGENT_REPLIED_TEMPLATE.format(
        actor=actor,
        action=action,
        number=number,
        app_ticket_url=payload['app_ticket_url'],
        plain_text_body=payload['plain_text_body']
    )

    return body

def get_event_handler(event: str) -> Callable[..., str]:
    # The main reason for this function existence is because of mypy
    handler = EVENTS_FUNCTION_MAPPER.get(event)  # type: Any
    if handler is None:
        raise UnexpectedWebhookEventType("Groove", event)
    return handler

@api_key_only_webhook_view('Groove')
@has_request_variables
def api_groove_webhook(request: HttpRequest, user_profile: UserProfile,
                       payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
    event = validate_extract_webhook_http_header(request, 'X_GROOVE_EVENT', 'Groove')
    assert event is not None
    handler = get_event_handler(event)

    body = handler(payload)
    topic = 'notifications'

    if body is not None:
        check_send_webhook_message(request, user_profile, topic, body)

    return json_success()

EVENTS_FUNCTION_MAPPER = {
    'ticket_started': ticket_started_body,
    'ticket_assigned': ticket_assigned_body,
    'agent_replied': partial(replied_body, actor='agent', action='replied to'),
    'customer_replied': partial(replied_body, actor='customer', action='replied to'),
    'note_added': partial(replied_body, actor='agent', action='left a note on')
}

fixture_to_headers = get_http_headers_from_filename("HTTP_X_GROOVE_EVENT")
