from dataclasses import dataclass, asdict
from typing import Optional, List, Dict, Union
from dacite import from_dict

from email.utils import getaddresses, parseaddr

import json
import requests

import messaging_support.types as hm_types


class RmConversationContext:
    
    def add_routed_message (self, rm):
        
        references = eml.get('References')
        
        
        return
        
class EmailConversationContext:
    
    def add_email (self, eml):
        
        # the first reference is the conversation starter
        # the last is the message this is a reply to
        # the middle are immediate replies, up to about 10 deep--
        # ie. some of the chain may be missing; we can get the oldest message
        #     and recursively rebuild upward
        references = eml.get('References')
        
        
        return


def addr_to_ra (addr):
    return {'name': addr[0], 'address': addr[1]}

class EmailSource:
    
    def __init__ (self, host, user, password):
        self.host = host
        self.user = user
        self.password = password
    
    def get_page (self, page=0, limit=10):
        
        resp = requests.get(f'http://localhost:5010/data/emails/imap?page={page}')
        if resp.status_code != 200:
            raise Exception(f'error: {resp.status_code}')
        
        resp_json = json.loads(resp.text)
        
        print(resp_json)
        
        # check_types=False because the string "None" creates a problem...
        
        root_key = resp_json['metaData']['root']
        fields = resp_json['metaData']['fields']
        rows = resp_json[ root_key ]
        
        data = []
        for i, row in enumerate(rows):
            msg_id = 'imap-' + str(i + (limit * page))
            record = {'msg_id': msg_id, **{k: row[j] for j, k in enumerate(fields)}}
            
            record['conversation_id'] = msg_id
            record['to'] = list(map(addr_to_ra, getaddresses([record['to']])))
            record['from_'] = list(map(addr_to_ra, getaddresses([record['from']])))[0]
            del record['from']
            
            rm = from_dict(data=record, data_class=hm_types.RoutedMessage)
            
            data.append(rm)
        
        routed_messages = data
        
        return routed_messages
        
    
    def get_page2 (self, page=0, limit=10):
        token = json.dumps({
            'host': self.host,
            'user': self.user,
            'password': self.password
        })
        
        headers = {
            'Authorization': token
        }
        
        resp = requests.get(f'http://localhost:5010/data/emails/imap2?page={page}', headers=headers)
        if resp.status_code != 200:
            raise Exception(f'error: {resp.status_code}')
        
        resp_json = json.loads(resp.text)
        
        routed_messages = list(map(lambda rm_dict: from_dict(data=rm_dict, data_class=hm_types.RoutedMessage), resp_json))
        
        return routed_messages

    def send_message (self, to, subject, content):
        
        token = json.dumps({
            'host': self.host,
            'user': self.user,
            'password': self.password
        })
        
        headers = {
            'Authorization': token
        }
        
        form_data = {
            'to': to,
            'subject': subject,
            'text': content
        }
        
        resp = requests.post('http://localhost:5010/api/send-message', data=form_data, headers=headers)
        
        return resp