import time
from datetime import datetime
import json
import requests
import base64
import hmac
import hashlib


class NCloud:
    host_name_url = "https://mail.apigw.ntruss.com" # 호스트 URL
    request_url = "/api/v1/mails"                   # 요청 URI
    access_key = "qNXWk443wdnDXrkPvoqr"             # 네이버 클라우드 플랫폼 회원에게 발급되는 개인 인증키
    secret_key = "umWxQXulhNSya2CkMNqqVJnSRfwRaN8BjMUX0skV"
                                                    # 2차 인증을 위해 서비스마다 할당되는 service secret
    api_key = "eWfapJfbR5W9NXPEsdXGzlJsShEV30DfxIV0d51J"
                                                    # API Gateway에서 발급받은 키(primary key 또는 secondary key)
    method = "POST"                                 # 요청 method mail 발송: POST, 발송 확인 GET
    request_id = ""                                 # 요청 ID


class MailSender:
    new_line = "\r\n"
    html_br_tag = "<br/>"

    # mail sender info
    sender_name = "초코마에"
    sender_email = "support+chocomae@jinaju.com"
    sender_address = sender_email
    sender_bcc = "support+chocomae.automail@jinaju.com"

    # bank account info
    bank_account_no = "3333-07-4977969"
    bank_name = "카카오뱅크"
    bank_owner_name = "박지상"

    def __init__(self):
        self.post_param = MailSender.make_default_post_param()

    def send_email(self, timestamp, signature):
        url = NCloud.host_name_url + NCloud.request_url
        # echo url."\n"

        headers = {
            'X-NCP-APIGW-TIMESTAMP': timestamp,
            'X-NCP-IAM-ACCESS-KEY': NCloud.access_key,
            'X-NCP-APIGW-SIGNATURE-V2': signature.decode('utf-8'),
            'Content-type': 'application/json'
        }
        # print(url)
        # print('headers : ' + json.dumps(headers, indent='\t'))
        # print('data : ' + json.dumps(self.post_param, indent='\t'))
        # exit(0)
        res = requests.post(url, headers=headers, data=json.dumps(self.post_param))

        print('sending mail result : {0}'.format(res.status_code))
        print('result text : \n{0}'.format(res.text))
        '''
        if res.status_code == 200:
            set_data("sendmail_respond", response)
            set_data("sendmail_post_param", post_param)
        elif res.status_code == 201:
            set_data("sendmail_succeed", response)
            set_data("sendmail_post_param", post_param)
        else:
            set_data("sendmail_error", response)
            set_data("sendmail_error_post_param", post_param)
        '''

    @staticmethod
    def make_request_url():
        if NCloud.method == "POST":
            return NCloud.host_name_url + NCloud.request_url
        else:
            return NCloud.host_name_url + NCloud.request_url + \
                   "/requests/" + NCloud.request_id + "/status"

    def set_post_param(self, key, value):
        self.post_param[key] = value

    def set_post_param_recipients(self, maestro_name, maestro_email):
        self.set_post_param('recipients', [
            {
                'address': maestro_email,
                'name': '',
                'type': 'R',
                'parameters': [
                    {'maestro_name': maestro_name}
                ]
            },
            {
                'address': MailSender.sender_bcc,
                'name': '',
                'type': 'B',
                'parameters': []
            }
        ])

    @staticmethod
    def make_default_post_param():
        post_param = {
            'advertising': False,   # 광고메일여부 default: False
            'attachFileIds': [],    # 첨부파일ID
            'body': '',             # Email 본문
            'individual': False,    # 개인발송여부 (개인발송 시 참조인, 숨은참조 무시됨) default: true
            'parameters': [],       # 치환 파라미터 (전체 수신자에게 적용), ‘치환 ID’ 를 key로,
                                    # ‘치환 ID에 맵핑되는 값’ 을 value로 가지는 Map 형태의 Object
            'recipients': [],
            'referencesHeader': '',     # 특정 메일을 모아서 보기 위해 네이버 메일에서 지원하는 기능,
                                        # 해당 필드에 동일한 값을 입력한 메일들을 모아서 볼 수 있다.
                                        # (다음의 형태가 되어야 함 : <unique_id@domain.com> )
            'reservationUtc': '',       # 예약 발송 일시 ( 1970년 1월 1일 00:00:00 협정 세계시(UTC)
                                        # 부터의 경과 시간을 1/1000초로 환산한 정수 ),
                                        # reservationDateTime 값보다 이 값이 우선 적용된다.
            'reservationDateTime': '',  # 다음과 같은 형태의 예약 발송 일시 (‘yyyy-MM-dd HH:mm’ UTC+09:00),
                                        # reservationUtc 값이 우선한다.
            'sender_address': MailSender.sender_email,
            'sender_name': MailSender.sender_name,
            'temprequest_id': '',       # 첨부파일 등록 시 사용한 임시 요청 ID
            'templateSid': 0,           # 템플릿 ID
            'title': ''
        }
        return post_param

    @staticmethod
    def get_timestamp():
        time_array = MailSender.micro_time().split(' ');
        microtime = time_array[0];
        timestamp = time_array[1];
        # print('microtime : ' + microtime)
        # print('timestamp : ' + timestamp)
        # print('microtime[2:5] : ' + microtime[2:5])
        return timestamp + microtime[2:5]

    @staticmethod
    def micro_time(get_as_float = False):
        d = datetime.now()
        t = time.mktime(d.timetuple())
        if get_as_float:
            return t
        else:
            ms = d.microsecond / 1000000.
            return '%f %d' % (ms, t)

    @staticmethod
    def hash_hmac(algo, data, key):
        res = hmac.new(key.encode(), data.encode(), algo).hexdigest()
        return res

    @staticmethod
    def b64encode(source):
        source = source.encode('utf=8')
        return base64.b64encode(source)
        # a = base64.b64encode(bytes(source.encode('utf-8')))
        # b = base64.b64decode(a).decode('utf-8', 'ignore')
        # return b

    @staticmethod
    def make_signature(url, timestamp):
        space = " "
        new_line = "\n"
        hmac_data = NCloud.method + space + url + new_line + timestamp + new_line + NCloud.access_key
        # print('hmac_data : ' + hmac_data)
        hash_hmac_data = MailSender.hash_hmac(hashlib.sha256, hmac_data, NCloud.secret_key)
        signature = MailSender.b64encode(hash_hmac_data)
        # signature = base64.b64encode(bytes(hash_hmac_data, 'utf-8'))
        # signature = hash_hmac_data
        return signature

    @staticmethod
    def send_temp_mail():
        post_param = {
            "advertising": False,  # 광고메일여부 default: False
            "attachFileIds": [],  # 첨부파일ID
            "body": "",  # Email 본문
            "individual": False,  # 개인발송여부 (개인발송 시 참조인, 숨은참조 무시됨) default: true
            "parameters": [],  # 치환 파라미터 (전체 수신자에게 적용), ‘치환 ID’ 를 key로,
            # ‘치환 ID에 맵핑되는 값’ 을 value로 가지는 Map 형태의 Object
            "recipients": [],
            "referencesHeader": "",  # 특정 메일을 모아서 보기 위해 네이버 메일에서 지원하는 기능,
            # 해당 필드에 동일한 값을 입력한 메일들을 모아서 볼 수 있다.
            # (다음의 형태가 되어야 함 : <unique_id@domain.com> )
            "reservationUtc": "",  # 예약 발송 일시 ( 1970년 1월 1일 00:00:00 협정 세계시(UTC)
            # 부터의 경과 시간을 1/1000초로 환산한 정수 ),
            # reservationDateTime 값보다 이 값이 우선 적용된다.
            "reservationDateTime": "",  # 다음과 같은 형태의 예약 발송 일시 (‘yyyy-MM-dd HH:mm’ UTC+09:00),
            # reservationUtc 값이 우선한다.
            "sender_address": MailSender.sender_email,
            "sender_name": MailSender.sender_name,
            "temprequest_id": "",  # 첨부파일 등록 시 사용한 임시 요청 ID
            "templateSid": 337,  # 템플릿 ID
            "title": ""
        }

        print(post_param)
        print('=' * 30)
        jsonData = json.dumps(post_param)
        print(jsonData)

        timestamp = MailSender.get_timestamp()
        signature = MailSender.make_signature(NCloud.request_url, timestamp)
        print(signature)

        url = NCloud.host_name_url + NCloud.request_url
        print(url)

        headers = {
            "X-NCP-APIGW-TIMESTAMP": timestamp,
            "X-NCP-IAM-ACCESS-KEY": NCloud.access_key,
            "X-NCP-APIGW-SIGNATURE-V2": signature.decode("utf-8"),
            "Content-type": "application/json"
        }
        print('headers : ' + json.dumps(headers, indent='\t'))
        # exit(0)
        res = requests.post(url, headers=headers, data=jsonData)

        print('sending mail result : {0}'.format(res.status_code))
        print('result text : \n{0}'.format(res.text))



'''
    @staticmethod
    def curl(post_param, timestamp, signature):
        if NCloud.method == "POST":
            is_post = True
        else:
            is_post = False

        try:
            url = NCloud.host_name_url + NCloud.request_url
            # echo url."\n"
            ch = curl_init()

            curl_setopt(ch, CURLOPT_URL, url)
            curl_setopt(ch, CURLOPT_POST, is_post)
            curl_setopt(ch, CURLOPT_RETURNTRANSFER, true)
            curl_setopt(ch, CURLOPT_SSL_VERIFYPEER, 0)
            if NCloud.method == "POST":
                curl_setopt(ch, CURLOPT_POSTFIELDS, post_param)

            headers = []
            headers[0] = "X-NCP-APIGW-TIMESTAMP: " + timestamp
            headers[1] = "X-NCP-IAM-ACCESS-KEY: " + NCloud.access_key
            headers[2] = "X-NCP-APIGW-SIGNATURE-V2: " + signature
            headers[3] = "content-type: application/json"
            curl_setopt(ch, CURLOPT_HTTPHEADER, headers)
            response = curl_exec(ch)

            status_code = curl_getinfo(ch, CURLINFO_HTTP_CODE)
            # echo "status_code:".status_code."\n"
            curl_close (ch)
            if status_code == 200:
                set_data("sendmail_respond", response)
                set_data("sendmail_post_param", post_param)
            elif status_code == 201:
                set_data("sendmail_succeed", response)
                set_data("sendmail_post_param", post_param)
            else :
                set_data("sendmail_error", response)
                set_data("sendmail_error_post_param", post_param)
        except E:
            set_data("sendmail_error", E.lastResponse)
            set_data("sendmail_error_post_param", post_param)
'''