{% extends "./assets/layout.html.twig" %}

{% block page %}
    {% if alreadyInstalled %}
        <h1 class='red'>Already installed</h1>

        <p>FOSSBilling already has a configuration file. To run the installer again, reset this instance first:</p>

        <ol>
            <li>Delete your database tables or recreate your database.</li>
            <li>Delete or repair <strong>config.php</strong>.</li>
            <li>Refresh this page to restart setup.</li>
        </ol>
    {% else %}
        <h1>Install FOSSBilling</h1>
        <p class="installer-intro">Set up the database connection, create the first admin account, and choose the default billing options.</p>

        <progress id="overall-progress" value="0" max="4"></progress>

        <hr />

        <form id='form' action="./install.php?a=install" method="post">
        <details {% if not canInstall %} open {% endif %} id="step-1">
            <summary>Step 1 - License Agreement</summary>

            <div class="choice-row">
                <input type="checkbox" id="agreement" name="agreement" required>
                <label for="agreement">I agree to the <a href='https://github.com/FOSSBilling/FOSSBilling/blob/master/LICENSE' target='_blank' data-tooltip="Opens in a new tab.">Apache License version 2.0,</a> and acknowledge that this software is provided as-is.</label>
            </div>
        </details>

        <details {% if not canInstall %} open {% endif %} id="step-2">
            <summary>Step 2 - System Requirements</summary>
            {% if canInstall %}
                <p class="green">This environment meets the basic installation requirements.</p>
            {% else %}
                <p class="red">Installation is blocked until the failed requirements below are fixed.</p>
            {% endif %}

            <div class="requirements-table-wrapper">
                <table role="grid">
                    <thead>
                        <tr>
                            <th scope="col">Requirement</th>
                            <th scope="col">Result</th>
                            <th scope="col"></th>
                        </tr>
                    </thead>
                    <tbody>
                        {% if is_subfolder %}
                            <tr>
                                <td>Subfolder detection</td>
                                <td class="red">FAIL</td>
                                <td>FOSSBilling must be installed at the host document root, not in a subfolder. See the <a href='https://docs.fossbilling.org/maintenance/troubleshooting/#subfolder-installations' data-tooltip="Opens in a new tab." target='_blank'>troubleshooting documentation</a>.</td>
                            </tr>
                        {% endif %}
                        <tr>
                            <td>Operating system</td>
                            <td class="{{ os_ok ? 'green' : 'orange'}}">{{ os }}</td>
                            <td>{% if not os_ok %}FOSSBilling may not work correctly on this operating system.{% endif %}</td>
                        </tr>
                        <tr>
                            <td>PHP version</td>
                            <td class="{{ compatibility.php_version.isOk ? 'green' : 'red'}}">{{ compatibility.php_version.version }}</td>
                            <td>{% if not compatibility.php_version.isOk %}PHP {{ compatibility.php_version.min_version }} or newer is required.{% endif %}</td>
                        </tr>
                        {% for ext, loaded in compatibility.required_extensions %}
                            <tr>
                                <td>PHP extension: <strong>{{ ext }}</strong></td>
                                <td class="{{ loaded ? 'green' : 'red'}}">{{ loaded ? 'OK' : 'FAIL'}}</td>
                                <td>{% if not loaded %}Enable the <strong>{{ ext }}</strong> PHP extension before continuing.{% endif %}</td>
                            </tr>
                        {% endfor %}
                        {% for ext, info in compatibility.suggested_extensions %}
                            {% if not info.loaded %}
                                <tr>
                                    <td>PHP extension: <strong>{{ ext }}</strong></td>
                                    <td class="{{ info.loaded ? 'green' : 'orange'}}">{{ info.loaded ? 'OK' : 'WARN'}}</td>
                                    <td>{% if not info.loaded %}Optional: {{ info.message }}.{% endif %}</td>
                                </tr>
                            {% endif %}
                        {% endfor %}
                        {% for file, writable in compatibility.files %}
                            {% if not writable %}
                                <tr>
                                    <td>{{ file }}</td>
                                    <td class="red">FAIL</td>
                                    <td>FOSSBilling cannot write to this file. <a href="https://docs.fossbilling.org/maintenance/troubleshooting/#permission-issues" target="_blank">Permission troubleshooting</a></td>
                                </tr>
                            {% endif %}
                        {% endfor %}
                        {% for folder, writable in compatibility.folders %}
                            {% if not writable %}
                                <tr>
                                    <td>{{ folder }}</td>
                                    <td class="red">FAIL</td>
                                    <td>Make sure this directory exists and is writable. <a href="https://docs.fossbilling.org/maintenance/troubleshooting/#permission-issues" target="_blank">Permission troubleshooting</a></td>
                                </tr>
                            {% endif %}
                        {% endfor %}
                    </tbody>
                </table>
            </div>
        </details>

        {% if canInstall == false %}

        <p>Fix the failed requirements, then refresh this page to continue setup.</p>

        {% else %}
                <details id="step-3">
                    <summary>Step 3 - Database Connection</summary>

                    <p>Enter the MySQL or MariaDB database details FOSSBilling should use.</p>

                    <fieldset>
                        <label for="database_hostname">Database Hostname <span class="red">*</span></label>
                        <input type="text" id="database_hostname" name="database_hostname" value="{{ request.database_hostname|default(database_hostname)|default('localhost') }}" placeholder="localhost, mysql, db.domain.com, 12.34.56.78 ..." required>
                        <small>Use the database service name in Docker environments, for example <strong>mariadb</strong>.</small>

                        <label for="database_port">Database Port <span class="red">*</span></label>
                        <input type="number" id="database_port" name="database_port" value="{{ request.database_port|default(3306) }}" placeholder="3306" required>

                        <label for="database_name">Database Name <span class="red">*</span></label>
                        <input type="text" id="database_name" name="database_name" value="{{ request.database_name|default(database_name) }}" placeholder="fossbilling" required>

                        <label for="database_username">Database Username <span class="red">*</span></label>
                        <input type="text" id="database_username" name="database_username" value="{{ request.database_username|default(database_username) }}" placeholder="fossbilling" required>

                        <label for="database_password">Database Password <span class="red">*</span></label>
                        <input type="password" id="database_password" name="database_password" value="{{ request.database_password|default(database_password) }}" placeholder="Database password" required>
                    </fieldset>
                </details>

                <details id="step-4">
                    <summary>Step 4 - Admin Account</summary>

                    <p>Create the first admin account. You will use this account to sign in to the admin area.</p>

                    <fieldset>
                        {% set minLength = 8 %}
                        <label for="admin_name">Name <span class="red">*</span></label>
                        <input type="text" id="admin_name" name="admin_name" value="{{ request.admin_name|default(admin_name) }}" placeholder="Your name" required>

                        <label for="admin_email">Email <span class="red">*</span></label>
                        <input type="email" id="admin_email" name="admin_email" value="{{ request.admin_email|default(admin_email) }}" placeholder="you@yourdomain.com" required>

                        <label for="admin_password">Password <span class="red">*</span></label>
                        <input type="password" id="admin_password" name="admin_password" value="{{ request.admin_password|default(admin_password) }}" placeholder="Create a strong password" required minlength="{{ minLength }}">
                        <small>
                            Password requirements:
                            <ul>
                                <li>Be at least {{ minLength }} characters long</li>
                                <li>Contain at least one number</li>
                                <li>Contain at least one lowercase letter</li>
                                <li>Contain at least one uppercase letter</li>
                            </ul>
                        </small>
                    </fieldset>
                </details>

                <details id="step-5">
                    <summary>Step 5 - Options</summary>

                    <section class="option-section first-option-section">
                        <h3>Billing</h3>
                        <p>Set the default currency used for invoices, orders, and product pricing. You can add more currencies later.</p>

                        <fieldset>
                            <label for="currency_code">Currency Code <span class="red">*</span></label>
                            <input type="text" id="currency_code" name="currency_code" value="{{ request.currency_code|default(currency_code) }}" required>
                        </fieldset>
                    </section>

                    <section class="option-section">
                        <h3>Public URL</h3>
                        <p>Confirm the address customers and staff should use to access this FOSSBilling installation.</p>

                        <fieldset>
                            <label for="system_url">FOSSBilling URL <span class="red">*</span></label>
                            <input type="url" id="system_url" name="system_url" value="{{ request.system_url|default(system_url) }}" placeholder="https://billing.example.com/" required>
                        </fieldset>
                    </section>

                    {% if proxy_candidate.detected|default(false) %}
                        <section class="option-section">
                            <h3>Reverse Proxy</h3>
                            <p>Forwarded headers were detected. Only enable trust if the address below is a reverse proxy you control and it removes untrusted forwarded headers from client requests.</p>

                            <div class="requirements-table-wrapper">
                                <table role="grid">
                                    <tbody>
                                        <tr>
                                            <td>Server received request from</td>
                                            <td><code>{{ proxy_candidate.remote_addr }}</code>{% if proxy_candidate.remote_addr_is_private %} (private/local address){% endif %}</td>
                                        </tr>
                                        <tr>
                                            <td>Detected header mode</td>
                                            <td><code>{{ proxy_candidate.headers }}</code></td>
                                        </tr>
                                        {% if proxy_candidate.suggested_url %}
                                            <tr>
                                                <td>Suggested public URL</td>
                                                <td><code>{{ proxy_candidate.suggested_url }}</code></td>
                                            </tr>
                                        {% endif %}
                                        {% for header, value in proxy_candidate.header_values %}
                                            <tr>
                                                <td>{{ header }}</td>
                                                <td><code>{{ value }}</code></td>
                                            </tr>
                                        {% endfor %}
                                    </tbody>
                                </table>
                            </div>

                            <div class="choice-row">
                                <input type="checkbox" id="trusted_proxy_enabled" name="trusted_proxy_enabled" value="1" {% if request.trusted_proxy_enabled|default(trusted_proxy_enabled) %} checked {% endif %}>
                                <label for="trusted_proxy_enabled">Trust this reverse proxy configuration.</label>
                            </div>

                            <fieldset>
                                <label for="trusted_proxy_proxies">Trusted proxy IP addresses</label>
                                <input type="text" id="trusted_proxy_proxies" name="trusted_proxy_proxies" value="{{ request.trusted_proxy_proxies|default(trusted_proxy_proxies) }}" placeholder="172.18.0.5">

                                <label for="trusted_proxy_headers">Trusted forwarded header format</label>
                                <select id="trusted_proxy_headers" name="trusted_proxy_headers">
                                    {% set selectedProxyHeaders = request.trusted_proxy_headers|default(trusted_proxy_headers) %}
                                    <option value="x_forwarded" {% if selectedProxyHeaders == 'x_forwarded' %} selected {% endif %}>X-Forwarded-* headers</option>
                                    <option value="forwarded" {% if selectedProxyHeaders == 'forwarded' %} selected {% endif %}>Forwarded header</option>
                                    <option value="aws_elb" {% if selectedProxyHeaders == 'aws_elb' %} selected {% endif %}>AWS ELB headers</option>
                                    <option value="traefik" {% if selectedProxyHeaders == 'traefik' %} selected {% endif %}>Traefik headers</option>
                                </select>
                            </fieldset>
                        </section>
                    {% endif %}

                    <section class="option-section">
                        <h3>Diagnostics</h3>
                        <p>Choose whether this installation can send scrubbed error reports to help maintainers identify defects.</p>

                        <div class="choice-row">
                            <input type="checkbox" id="error-reporting" name="error_reporting">
                            <label for="error-reporting">Enable automated error reporting.</label>
                        </div>
                        <small class="choice-help">Optional. <a href="#" data-target="learn-reporting" onClick="toggleModal(event)">Learn more</a></small>
                    </section>
                </details>

                <div class="installer-actions">
                    <progress id='progress' style='display:none;'></progress>

                    <button class="secondary" id="backButton" type="button" disabled>Back</button>
                    <button id='nextButton' type="button">Next</button>

                    <button id='button' type="submit" hidden="true">Install</button>
                </div>
                <div>
                    <p id="time-note" class="installer-note" hidden="true">Installation can take a short moment while database tables and default templates are created.</p>
                </div>
        </form>
        {% endif %}

        <!-- Below is the "learn more" modal for error and performance reporting -->
        <dialog id="learn-reporting">
            <article>
                <a href="#close"
                    aria-label="Close"
                    class="close"
                    data-target="learn-reporting"
                    onClick="toggleModal(event)">
                </a>
                <h3>Error reporting</h3>
                <p>Automated error reporting helps the FOSSBilling team identify defects and improve stability.</p>
                <p>Reports are collected using <a href="https://sentry.io/welcome/" target='_blank' data-tooltip="Opens in a new tab.">Sentry.io</a> and retained for up to 90 days under Sentry's <a href="https://sentry.io/security/" target='_blank' data-tooltip="Opens in a new tab.">security practices</a>.</p>
                <p>Data scrubbing and filtering are applied to reduce the chance of sensitive information being recorded.</p>
                <p>See <a href="https://docs.fossbilling.org/maintenance/error-reporting/" target='_blank' data-tooltip="Opens in a new tab.">the FOSSBilling documentation</a> for details about what is collected.</p>
                <footer>
                    <a href="#confirm"
                        role="button"
                        data-target="learn-reporting"
                        onClick="toggleModal(event)">
                        Got it
                    </a>
                </footer>
            </article>
        </dialog>
    {% endif %}
{% endblock %}

{% block javascript %}
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            var currentStep = 1;
            var completedStep = 0;
            const button = document.getElementById('button');
            const timeNote = document.getElementById('time-note');
            const progress = document.getElementById('progress');
            const form = document.getElementById('form');
            const backButton = document.getElementById('backButton');
            const nextButton = document.getElementById('nextButton');
            const step1 = document.getElementById("step-1");
            const step2 = document.getElementById("step-2");
            const step3 = document.getElementById("step-3");
            const step4 = document.getElementById("step-4");
            const step5 = document.getElementById("step-5");
            const steps = [step1, step2, step3, step4, step5];

            function isStepAllowed(step, reportValidity = false) {
                for (let i = 1; i < step; i++) {
                    if(!checkRequiredInputs(i, false)){
                        if (reportValidity) {
                            currentStep = i;
                            updateStepVisibility(currentStep);
                            updateButtons();
                            updateProgress();
                            setTimeout(() => checkRequiredInputs(i, true), 0);
                        }

                        return false;
                    }
                }
                return step <= 6;
            }

            function updateStepVisibility(step) {
                steps.forEach((stepElement, index) => {
                    stepElement.open = index + 1 === step ? true : false;
                });
            }

            function checkRequiredInputs(step, reportValidity = false) {
                const stepForm = document.getElementById(`step-${step}`);
                var requiredInputs = stepForm.querySelectorAll('input[required]');
                var allowed = true;

                requiredInputs.forEach(function (input) {
                    const isValid = reportValidity ? input.reportValidity() : input.checkValidity();
                    if (!isValid) {
                        allowed = false;
                    }
                });

                return allowed;
            }

            function updateButtons() {
                backButton.disabled = currentStep === 1;
                nextButton.disabled = currentStep === 6 || {{ canInstall ? 'false' : 'true' }};

                if(currentStep === 5){
                    nextButton.hidden = true;
                    timeNote.hidden   = false;
                    button.hidden     = false;
                } else {
                    nextButton.hidden = false;
                    timeNote.hidden   = true;
                    button.hidden     = true
                }
            }

            function updateProgress() {
                const overallProgress = document.getElementById('overall-progress');
                overallProgress.value = completedStep;
            }

            updateButtons();
            updateStepVisibility(currentStep);
            updateProgress();

            form.addEventListener('submit', e => {
                button.disabled = true;
                button.style.display = 'none';
                progress.style.display = 'block';
            });

            backButton.addEventListener('click', () => {
                if (currentStep > 1) {
                    currentStep--;
                    updateStepVisibility(currentStep);
                    updateButtons();
                }
            });

            nextButton.addEventListener('click', () => {
                if({{ canInstall ? 'true' : 'false' }} && isStepAllowed(currentStep + 1, true)){
                    completedStep = Math.max(completedStep, currentStep);
                    currentStep++;
                    updateStepVisibility(currentStep);
                    updateButtons();
                    updateProgress();
                }
            });

            steps.forEach((stepElement, index) => {
                stepElement.addEventListener('toggle', () => {
                    if (!stepElement.open || currentStep === index + 1) {
                        return;
                    }

                    currentStep = index + 1;
                    updateStepVisibility(currentStep);
                    updateButtons();
                });
            });
        });
    </script>
{% endblock %}
