import os
import os.path
import re
import urllib.parse
import json
import subprocess

from Mailman.Logging.Syslog import syslog

PERL_BIN = '/usr/local/cpanel/3rdparty/bin/perl'

def allowConsentGathering():
    leika_consent_required = None
    try:
        result = subprocess.run(
            [
                PERL_BIN,
                '-MCpanel::Analytics',
                '-e',
                'print Cpanel::Analytics::is_user_analytics_consent_required_by_leika()'
            ],
            check=True,
            capture_output=True,
            text=True,
            timeout=2,
        )
        leika_consent_required = True if result.stdout.strip() == '1' else False
    except Exception as e:
        # If is_user_analytics_consent_required_by_leika() is not implemented,
        # we default to requiring consent.
        leika_consent_required = True
        syslog('error', "Mixpanel error: Perl consent check failed: %s", e)

    return leika_consent_required


def analyticsEnabledByAdmin():

    # Known as UI_INCLUDES_TOUCH_FILE in /usr/local/cpanel
    try:
        if os.path.exists('/var/cpanel/feature_toggles/analytics_ui_includes'):
            return True
    except Exception as e:
        syslog('error', "Mixpanel error: analytics_ui_includes file check: %s", e)

    return False

# Compare:
#   isQaBuild in ui/web-components/src/components/shared/cp-ui-analytics/mixpanel/mixpanel-utils.service.ts
#   _is_dev_environment in Cpanel/Analytics/Mixpanel.pm
def isDevEnvironment():
    try:
        if os.path.exists('/var/cpanel/dev_sandbox'):
            return True
    except Exception as e:
        syslog('error', "Mixpanel error: dev_sandbox file check: %s", e)

    isNat = False
    try:
        natSize = os.path.getsize('/var/cpanel/cpnat');
        if natSize != 0:
            isNat = True
    except FileNotFoundError:
        pass
    except Exception as e:
        syslog('error', "Mixpanel error: cpnat file check: %s", e)

    isPrivate = False
    try:
        with open('/var/cpanel/mainip') as mainIpFile:
            mainIp = mainIpFile.read()
            if re.search('^10\.', mainIp):
                isPrivate = True
    except Exception as e:
        syslog('error', "Mixpanel error: mainip file check: %s", e)

    if not isNat and isPrivate:
        return True

    return False

def existingIdentity():
    qs = os.environ.get('QUERY_STRING', '')
    parsed = urllib.parse.parse_qs(qs)
    if parsed:
        raw_identity = parsed.get('mpidentity')
        if raw_identity:
            identity = urllib.parse.quote( raw_identity[-1] )
            return identity
    return None

def cleansedPathInfo():
    requestUri = os.environ.get('REQUEST_URI')

    path = {}

    # Extract the admin subpage name without including the security token or the mailing list name
    adminMatch = re.search('/mailman/admin/[^/]+(/[^?/]*)', requestUri)
    if adminMatch:
        path['isAdmin'] = True
        path['section'] = adminMatch.group(1)
    else:
        path['isAdmin'] = False
        path['section']    = 'N/A'

    return path

def HTML():

    pageData = {}

    pageData['allowConsentGathering'] = allowConsentGathering()

    if ( pageData['allowConsentGathering'] and not analyticsEnabledByAdmin() ):
        return ''

    pageData['isDevEnvironment'] = isDevEnvironment()
    pageData['identity']         = existingIdentity()
    pageData['path']             = cleansedPathInfo()

    return '''
<style>
.consentModal {
    position: fixed;
    z-index: 1;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    overflow: auto;
    background-color: rgba(0,0,0,0.6);
}

.floatingConsent {
    position: fixed;
    top: 45%;
    left: 0;
    right: 0;
    filter: drop-shadow(4px 4px 2px rgb(20,20,20,0.7));
}

.floatingConsent #fullConsentDialog {
    display: block;
}

.floatingConsent #compactConsentDialog {
    display: none;
}

.nonFloatingConsent {
}

.hide { display: none; }
.show { display: block; }

.nonFloatingConsent #fullConsentDialog {
    display: none;
}

.nonFloatingConsent #compactConsentDialog {
    display: block;
}

.baseConsent {
    width: 80%;
    background-color: white;
    border: 1px solid black;
    border-radius: 5px;
    margin-left: auto;
    margin-right: auto;
    margin-bottom: 20px;
    padding: 10px;
    font-family: sans-serif;
}

.baseConsent a, a:visited {
    color: rgb(0, 46, 128);
    text-decoration: none;
    cursor: pointer;
}

.consentButtons .mixpanelSaveButton {
    margin-top: 5px;
    margin-left: 5px;
    margin-right: 5px;
    margin-bottom: 15px;
    background-color: rgb(0, 46, 128);
    font-family: sans-serif;
    font-size: 1em;
    color: white;
    border-radius: 10px;
    border: 0;
    padding: 10px;
    cursor: pointer;
}

.mixpanelSaveButton:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.consentButtons ul {
    padding: 0;
    list-style-type: none;
}

.consentButtons li {
    padding: 5px;
}

</style>

<div id="consentContainer">
    <div class="baseConsent nonFloatingConsent" id="mixpanelConsentQuestion">
        <div id="fullConsentDialog">
            <h2>Consent and Privacy</h2>
            <div>
            WebPros International, LLC d.b.a cPanel is asking for your consent to participate in user activity tracking using third-party software for the purpose of understanding the performance of WebPros products. Information will be used pursuant to the <a href="https://go.cpanel.net/privacy" target="_blank">cPanel &amp; WHM Privacy Policy</a> and may be shared internally within the WebPros group. You can update your preferences at any time. <a href="https://go.cpanel.net/analytics" target="_blank">Learn more here.</a>
            </div>
            <div class="consentButtons">
                <div>
                <ul>
                    <li><input type=radio name="mixpanelTrackingChoice" value="opt_in" id="mixpanelTrackingChoiceOptIn"><label for="mixpanelTrackingChoiceOptIn">Allow data collection</label></li>
                    <li><input type=radio name="mixpanelTrackingChoice" value="opt_in" id="mixpanelTrackingChoiceOptOut"><label for="mixpanelTrackingChoiceOptOut">Deny data collection</label></li>
                </ul>
                </div>
                <div>
                    <input type=button class="mixpanelSaveButton" id="mixpanelTrackingSave" value="Save and Continue">
                </div>
            </div>
        </div>
        <div id="compactConsentDialog">
            <span id="mixpanelConsentOptedInText" class="hide">You have opted in to tracking.</span>
            <span id="mixpanelConsentOptedOutText" class="hide">You have opted out of tracking.</span>
            <span>You may <a id="mixpanelTrackingReconfigure">change this setting</a> at any time.</span>
        </div>
    </div>
</div>

<script type="text/javascript">

// https://docs.mixpanel.com/docs/quickstart/install-mixpanel?sdk=javascript
(function (f, b) { if (!b.__SV) { var e, g, i, h; window.mixpanel = b; b._i = []; b.init = function (e, f, c) { function g(a, d) { var b = d.split("."); 2 == b.length && ((a = a[b[0]]), (d = b[1])); a[d] = function () { a.push([d].concat(Array.prototype.slice.call(arguments, 0))); }; } var a = b; "undefined" !== typeof c ? (a = b[c] = []) : (c = "mixpanel"); a.people = a.people || []; a.toString = function (a) { var d = "mixpanel"; "mixpanel" !== c && (d += "." + c); a || (d += " (stub)"); return d; }; a.people.toString = function () { return a.toString(1) + ".people (stub)"; }; i = "disable time_event track track_pageview track_links track_forms track_with_groups add_group set_group remove_group register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking start_batch_senders people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user people.remove".split( " "); for (h = 0; h < i.length; h++) g(a, i[h]); var j = "set set_once union unset remove delete".split(" "); a.get_group = function () { function b(c) { d[c] = function () { call2_args = arguments; call2 = [c].concat(Array.prototype.slice.call(call2_args, 0)); a.push([e, call2]); }; } for ( var d = {}, e = ["get_group"].concat( Array.prototype.slice.call(arguments, 0)), c = 0; c < j.length; c++) b(j[c]); return d; }; b._i.push([e, f, c]); }; b.__SV = 1.2; e = f.createElement("script"); e.type = "text/javascript"; e.async = !0; e.src = "undefined" !== typeof MIXPANEL_CUSTOM_LIB_URL ? MIXPANEL_CUSTOM_LIB_URL : "file:" === f.location.protocol && "//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\/\//) ? "https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js" : "//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js"; g = f.getElementsByTagName("script")[0]; g.parentNode.insertBefore(e, g); } })(document, window.mixpanel || []);

(function() {
    var pageData = ''' + json.dumps(pageData) + ''';
    var mixpanelToken = pageData.isDevEnvironment ? 'c7c6f1b1bc8e7b3d8254ebe545861955' : '2cca34424fe0e8ad6897d354b9591c45';

    if (!pageData.allowConsentGathering) {
        var consentDiv = document.getElementById('consentContainer');
        if (consentDiv) {
            consentDiv.style.display = 'none';
        }
    }

    var addClass     = function(elemId, theClass) { return document.getElementById(elemId).classList.add(theClass);    };
    var removeClass  = function(elemId, theClass) { return document.getElementById(elemId).classList.remove(theClass); };
    var radioUncheck = function(elemId) {           return document.getElementById(elemId).checked = false;            };
    var isChecked    = function(elemId) {           return document.getElementById(elemId).checked;                    };
    var btnDisable   = function(elemId, state) {    return document.getElementById(elemId).disabled = state;           };

    var showModal = function() {
        if (!pageData.allowConsentGathering) return;
        addClass('mixpanelConsentQuestion',    'floatingConsent');
        removeClass('mixpanelConsentQuestion', 'nonFloatingConsent');
        addClass('consentContainer',           'consentModal');
    };
    var hideModal = function() {
        removeClass('mixpanelConsentQuestion', 'floatingConsent');
        addClass('mixpanelConsentQuestion',    'nonFloatingConsent');
        removeClass('consentContainer',        'consentModal');
    }

    var setupConsent = function(mixp) {
        var CONSENT_OPTED_IN    = 'opted_in';
        var CONSENT_OPTED_OUT   = 'opted_out';
        var CONSENT_UNSPECIFIED = 'unspecified';

        var importIdentity = function() {
            if (pageData.identity) {
                mixpanel.identify(pageData.identity);
            }
            // else: no problem; a new identity will be created automatically
        }

        if (!pageData.allowConsentGathering) {
            mixp.opt_in_tracking();
        }

        var consentStatus;
        if (mixp.has_opted_in_tracking()) {
            consentStatus = CONSENT_OPTED_IN;
            importIdentity()
            if (pageData.path.isAdmin) {
                mixp.track('Mailman-Admin', { section: pageData.path.section });
            }
            else {
                mixp.track('Mailman-User');
            }
        }
        else if (mixp.has_opted_out_tracking()) {
            consentStatus = CONSENT_OPTED_OUT;
        }
        else {
            consentStatus = CONSENT_UNSPECIFIED;
            showModal();
        }

        var updateDisplayedConsentStatus = function(newStatus) {
            if (newStatus === CONSENT_UNSPECIFIED) {
                showModal();
                radioUncheck('mixpanelTrackingChoiceOptIn');
                radioUncheck('mixpanelTrackingChoiceOptOut');
                btnDisable('mixpanelTrackingSave', true);
            }
            else {
                hideModal();
                btnDisable('mixpanelTrackingSave', false);

                if (newStatus == CONSENT_OPTED_IN) {
                    removeClass('mixpanelConsentOptedInText', 'hide');
                    addClass('mixpanelConsentOptedOutText',   'hide');
                }
                else if (newStatus == CONSENT_OPTED_OUT) {
                    addClass('mixpanelConsentOptedInText',     'hide');
                    removeClass('mixpanelConsentOptedOutText', 'hide');
                }
            }

        };
        updateDisplayedConsentStatus(consentStatus);

        document.getElementById('mixpanelTrackingSave').addEventListener('click', function() {
            if (isChecked('mixpanelTrackingChoiceOptIn')) {
                importIdentity()
                mixp.opt_in_tracking()
                updateDisplayedConsentStatus(CONSENT_OPTED_IN);
            }
            else if (isChecked('mixpanelTrackingChoiceOptOut')) {
                mixp.opt_out_tracking()
                updateDisplayedConsentStatus(CONSENT_OPTED_OUT);
            }
            else {
                // Should never get here because the button is disabled until they select allow or deny.
            }
        } );

        document.getElementById('mixpanelTrackingReconfigure').addEventListener('click', function() {
            updateDisplayedConsentStatus(CONSENT_UNSPECIFIED); // Pop the dialog back up
        } );

        ['mixpanelTrackingChoiceOptIn', 'mixpanelTrackingChoiceOptOut'].forEach( function(btn) {
            document.getElementById(btn).addEventListener('click', function() {
                btnDisable('mixpanelTrackingSave', false);
            });
        } );
    };

    mixpanel.init(
        mixpanelToken,
        {
            debug: true,
            persistence: "localStorage",
            opt_out_of_tracking_by_default: true,
            track_pageview: false,
            property_blacklist: [
                "$initial_referrer",
                "$referrer",
                "$current_url",
                "url",
            ],
            ip: false,
            autotrack: false,
            api_host: "https://mixpanel-proxy.cpanel.net",
            loaded: setupConsent,
        }
    );
})();
</script>
'''
