"""DPO Pay API client for subscription checkout."""
import re
from datetime import datetime
from xml.etree import ElementTree as ET

import requests
from django.conf import settings


class DPOClient:
    endpoint_url = 'https://secure.3gdirectpay.com/API/v6/'
    hosted_pay_url = 'https://secure.3gdirectpay.com/payv2.php'

    @staticmethod
    def company_token():
        return getattr(settings, 'DPO_COMPANY_TOKEN', '')

    @staticmethod
    def service_type():
        return getattr(settings, 'DPO_SERVICE_TYPE', '88938')

    @staticmethod
    def sanitize_phone_number(phone):
        if not phone:
            return '260000000000'
        clean_phone = re.sub(r'\D', '', str(phone))
        if len(clean_phone) < 6:
            return '260000000000'
        return clean_phone[:20]

    @classmethod
    def create_charge_token(
        cls,
        *,
        company_ref,
        amount,
        currency,
        redirect_url,
        back_url,
        service_description,
        customer_first_name,
        customer_last_name,
        customer_email,
        customer_phone,
        customer_country='ZM',
        customer_city='Lusaka',
    ):
        service_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        sanitized_phone = cls.sanitize_phone_number(customer_phone)
        xml_data = f"""<?xml version="1.0" encoding="utf-8"?>
<API3G>
    <CompanyToken>{cls.company_token()}</CompanyToken>
    <Request>createToken</Request>
    <Transaction>
        <PaymentAmount>{amount}</PaymentAmount>
        <PaymentCurrency>{currency}</PaymentCurrency>
        <customerFirstName>{customer_first_name}</customerFirstName>
        <customerLastName>{customer_last_name}</customerLastName>
        <customerEmail>{customer_email}</customerEmail>
        <customerCountry>{customer_country}</customerCountry>
        <customerCity>{customer_city}</customerCity>
        <customerPhone>{sanitized_phone}</customerPhone>
        <CompanyRef>{company_ref}</CompanyRef>
        <RedirectURL>{redirect_url}</RedirectURL>
        <BackURL>{back_url}</BackURL>
        <CompanyRefUnique>0</CompanyRefUnique>
        <PTL>15</PTL>
    </Transaction>
    <Services>
        <Service>
            <ServiceType>{cls.service_type()}</ServiceType>
            <ServiceDescription>{service_description}</ServiceDescription>
            <ServiceDate>{service_date}</ServiceDate>
        </Service>
    </Services>
</API3G>"""
        response = requests.post(
            cls.endpoint_url,
            data=xml_data,
            headers={'Content-Type': 'application/xml'},
            timeout=30,
        )
        return ET.fromstring(response.text)

    @classmethod
    def charge_mobile_money(
        cls,
        *,
        company_ref,
        amount,
        currency,
        redirect_url,
        back_url,
        service_description,
        customer_first_name,
        customer_last_name,
        customer_email,
        customer_phone,
        customer_country,
        customer_city,
        network,
        mobile_phone,
    ):
        token_root = cls.create_charge_token(
            company_ref=company_ref,
            amount=amount,
            currency=currency,
            redirect_url=redirect_url,
            back_url=back_url,
            service_description=service_description,
            customer_first_name=customer_first_name,
            customer_last_name=customer_last_name,
            customer_email=customer_email,
            customer_phone=customer_phone,
            customer_country=customer_country,
            customer_city=customer_city,
        )
        result = token_root.find('Result')
        if result is None or result.text != '000':
            explanation = token_root.find('ResultExplanation')
            message = explanation.text if explanation is not None else 'Could not create payment token.'
            return {'success': False, 'message': message, 'token': None}

        transaction_token = token_root.find('TransToken').text
        sanitized_mobile = cls.sanitize_phone_number(mobile_phone)
        xml_data = f"""<?xml version="1.0" encoding="UTF-8"?>
<API3G>
    <CompanyToken>{cls.company_token()}</CompanyToken>
    <Request>ChargeTokenMobile</Request>
    <TransactionToken>{transaction_token}</TransactionToken>
    <PhoneNumber>{sanitized_mobile}</PhoneNumber>
    <MNO>{network}</MNO>
    <MNOcountry>zambia</MNOcountry>
</API3G>"""
        response = requests.post(
            cls.endpoint_url,
            data=xml_data,
            headers={'Content-Type': 'application/xml'},
            timeout=30,
        )
        charge_root = ET.fromstring(response.text)
        charge_result = charge_root.find('Result')
        success_codes = {'000', '130', '100'}
        is_success = charge_result is not None and charge_result.text in success_codes
        explanation = charge_root.find('ResultExplanation')
        return {
            'success': is_success,
            'message': explanation.text if explanation is not None else response.text,
            'token': transaction_token,
            'raw_response': response.text,
        }

    @classmethod
    def verify_token(cls, transaction_token):
        xml_data = f"""<?xml version="1.0" encoding="UTF-8"?>
<API3G>
    <CompanyToken>{cls.company_token()}</CompanyToken>
    <Request>verifyToken</Request>
    <TransactionToken>{transaction_token}</TransactionToken>
</API3G>"""
        response = requests.post(
            cls.endpoint_url,
            data=xml_data,
            headers={'Content-Type': 'application/xml'},
            timeout=30,
        )
        root = ET.fromstring(response.text)
        result = root.find('Result')
        if result is None:
            return 'pending'
        if result.text == '000':
            return 'success'
        if result.text in {'903', '904'}:
            return 'rejected'
        return 'pending'

    @classmethod
    def hosted_checkout_url(cls, transaction_token):
        return f'{cls.hosted_pay_url}?ID={transaction_token}'
