#!/usr/local/cpanel/3rdparty/bin/perl
# gniza4cp WHM Plugin — Main Config Editor
use strict;
use warnings;

use lib '/usr/local/cpanel/whostmgr/docroot/cgi/gniza4cp-whm/lib';

use Whostmgr::HTMLInterface ();
use Cpanel::Form            ();
use Gniza4cpWHM::Config;
use Gniza4cpWHM::Validator;
use Gniza4cpWHM::UI;

my $CONFIG_FILE = '/etc/gniza4cp/gniza4cp.conf';
my $form        = Cpanel::Form::parseform();
my $method      = $ENV{'REQUEST_METHOD'} // 'GET';
my $action      = $form->{'action'} // '';

# ── Handle SMTP Test (JSON) ──────────────────────────────────

if ($action eq 'test_smtp') {
    print "Content-Type: application/json\r\n\r\n";

    unless ($method eq 'POST' && Gniza4cpWHM::UI::verify_csrf_token($form->{'gniza4cp_csrf'})) {
        print qq({"success":false,"message":"Invalid or expired token. Please reload and try again."});
        exit;
    }

    # Generate fresh token after consuming the old one
    my $new_csrf = Gniza4cpWHM::UI::generate_csrf_token();

    my $host     = $form->{'SMTP_HOST'} // '';
    my $port     = $form->{'SMTP_PORT'} || '587';
    my $user     = $form->{'SMTP_USER'} // '';
    my $password = $form->{'SMTP_PASSWORD'} // '';
    my $from     = $form->{'SMTP_FROM'} // '';
    my $security = $form->{'SMTP_SECURITY'} || 'tls';
    my $to       = $form->{'NOTIFY_EMAIL'} // '';

    if ($host eq '') {
        print qq({"success":false,"message":"SMTP Host is required.","csrf":"$new_csrf"});
        exit;
    }
    if ($to eq '') {
        print qq({"success":false,"message":"Notification email is required for test.","csrf":"$new_csrf"});
        exit;
    }

    my ($ok, $err) = Gniza4cpWHM::UI::test_smtp_connection(
        host     => $host,
        port     => $port,
        user     => $user,
        password => $password,
        from     => $from,
        security => $security,
        to       => $to,
    );
    if ($ok) {
        print qq({"success":true,"message":"Test email sent successfully. Check your inbox.","csrf":"$new_csrf"});
    } else {
        $err //= 'Unknown error';
        $err =~ s/\\/\\\\/g;
        $err =~ s/"/\\"/g;
        $err =~ s/\n/\\n/g;
        $err =~ s/\r/\\r/g;
        $err =~ s/\t/\\t/g;
        $err =~ s/[\x00-\x1f]//g;
        print qq({"success":false,"message":"SMTP test failed: $err","csrf":"$new_csrf"});
    }
    exit;
}

# ── Handle POST ──────────────────────────────────────────────

my @errors;
my $saved = 0;

if ($method eq 'POST') {
    unless (Gniza4cpWHM::UI::verify_csrf_token($form->{'gniza4cp_csrf'})) {
        push @errors, 'Invalid or expired form token. Please try again.';
    }

    if (!@errors) {
        my %data;
        for my $key (@Gniza4cpWHM::Config::MAIN_KEYS) {
            $data{$key} = $form->{$key} // '';
        }

        my $validation_errors = Gniza4cpWHM::Validator::validate_main_config(\%data);

        if (@$validation_errors) {
            @errors = @$validation_errors;
        } else {
            my ($ok, $err) = Gniza4cpWHM::Config::save($CONFIG_FILE, \%data, \@Gniza4cpWHM::Config::MAIN_KEYS);
            if ($ok) {
                Gniza4cpWHM::UI::set_flash('success', 'Configuration saved successfully.');
                print "Status: 302 Found\r\n";
                print "Location: settings.cgi\r\n\r\n";
                exit;
            } else {
                push @errors, "Failed to save config: $err";
            }
        }
    }
}

# ── Render Page ──────────────────────────────────────────────

print "Content-Type: text/html\r\n\r\n";

Whostmgr::HTMLInterface::defheader('GNIZA Backup Manager — Settings', '', '/cgi/gniza4cp-whm/settings.cgi');

print Gniza4cpWHM::UI::page_header('Settings');
print Gniza4cpWHM::UI::render_nav('settings.cgi');
print Gniza4cpWHM::UI::render_flash();

if (@errors) {
    print Gniza4cpWHM::UI::render_errors(\@errors);
}

# Load current config (or use POST data if validation failed)
my $conf;
if (@errors && $method eq 'POST') {
    $conf = {};
    for my $key (@Gniza4cpWHM::Config::MAIN_KEYS) {
        $conf->{$key} = $form->{$key} // '';
    }
} else {
    $conf = Gniza4cpWHM::Config::parse($CONFIG_FILE, 'main');
}

# Helper to output a text field row
sub field_text {
    my ($key, $label, $hint, $extra, $tip) = @_;
    $extra //= '';
    my $val = Gniza4cpWHM::UI::esc($conf->{$key} // '');
    my $hint_html = $hint ? qq{ <span class="text-xs text-base-content/60 ml-2">} . Gniza4cpWHM::UI::esc($hint) . qq{</span>} : '';
    my $tip_html = $tip ? qq{ <span class="tooltip tooltip-top" data-tip="} . Gniza4cpWHM::UI::esc($tip) . qq{">&#9432;</span>} : '';
    print qq{<div class="flex items-center gap-3 mb-2.5">\n};
    print qq{  <label class="w-44 font-medium text-sm whitespace-nowrap" for="$key">$label$tip_html</label>\n};
    print qq{  <input type="text" class="input input-bordered input-sm w-full max-w-xs" id="$key" name="$key" value="$val" $extra>\n};
    print qq{  $hint_html\n} if $hint;
    print qq{</div>\n};
}

# Helper to output a select field row
sub field_select {
    my ($key, $label, $options_ref) = @_;
    my $current = $conf->{$key} // '';
    print qq{<div class="flex items-center gap-3 mb-2.5">\n};
    print qq{  <label class="w-44 font-medium text-sm" for="$key">$label</label>\n};
    print qq{  <select class="select select-bordered select-sm w-full max-w-xs" id="$key" name="$key">\n};
    for my $opt (@$options_ref) {
        my $sel = ($current eq $opt) ? ' selected' : '';
        my $esc_opt = Gniza4cpWHM::UI::esc($opt);
        print qq{    <option value="$esc_opt"$sel>$esc_opt</option>\n};
    }
    print qq{  </select>\n};
    print qq{</div>\n};
}

# ── Form ─────────────────────────────────────────────────────

print qq{<form method="POST" action="settings.cgi">\n};
print Gniza4cpWHM::UI::csrf_hidden_field();

# Section: Local Settings
print qq{<div class="card bg-white shadow-sm border border-base-300 mb-6">\n<div class="card-body">\n};
print qq{<h2 class="card-title text-sm">Local Settings</h2>\n};
field_text('TEMP_DIR', 'Working Directory', 'Default: /usr/local/gniza4cp/workdir', '', 'Temporary directory used for pkgacct output before transfer');
print qq{</div>\n</div>\n};

# Section: Account Filtering
print qq{<div class="card bg-white shadow-sm border border-base-300 mb-6">\n<div class="card-body">\n};
print qq{<h2 class="card-title text-sm">Account Filtering</h2>\n};
my $inc_val = Gniza4cpWHM::UI::esc($conf->{INCLUDE_ACCOUNTS} // '');
my $exc_val = Gniza4cpWHM::UI::esc($conf->{EXCLUDE_ACCOUNTS} // '');
print qq{<div class="flex items-center gap-3 mb-2.5">\n};
print qq{  <label class="w-44 font-medium text-sm whitespace-nowrap" for="INCLUDE_ACCOUNTS">Include Accounts <span class="tooltip tooltip-top" data-tip="Only back up these accounts. Leave empty to back up all accounts.">&#9432;</span></label>\n};
print qq{  <textarea class="textarea textarea-bordered textarea-sm w-full max-w-xs" id="INCLUDE_ACCOUNTS" name="INCLUDE_ACCOUNTS" placeholder="Comma-separated, empty = all">$inc_val</textarea>\n};
print qq{</div>\n};
print qq{<div class="flex items-center gap-3 mb-2.5">\n};
print qq{  <label class="w-44 font-medium text-sm whitespace-nowrap" for="EXCLUDE_ACCOUNTS">Exclude Accounts <span class="tooltip tooltip-top" data-tip="These accounts will never be backed up">&#9432;</span></label>\n};
print qq{  <textarea class="textarea textarea-bordered textarea-sm w-full max-w-xs" id="EXCLUDE_ACCOUNTS" name="EXCLUDE_ACCOUNTS" placeholder="Comma-separated">$exc_val</textarea>\n};
print qq{</div>\n};

my @accounts = Gniza4cpWHM::UI::get_cpanel_accounts();
if (@accounts) {
    print qq{<div class="text-xs text-base-content/60 mt-2">};
    print qq{Available accounts: } . Gniza4cpWHM::UI::esc(join(', ', @accounts));
    print qq{</div>\n};
}
print qq{</div>\n</div>\n};

# Section: Logging
print qq{<div class="card bg-white shadow-sm border border-base-300 mb-6">\n<div class="card-body">\n};
print qq{<h2 class="card-title text-sm">Logging</h2>\n};
field_text('LOG_DIR', 'Log Directory', 'Default: /var/log/gniza4cp');
field_select('LOG_LEVEL', 'Log Level', ['debug', 'info', 'warn', 'error']);
field_text('LOG_RETAIN', 'Log Retention (days)', 'Default: 90', '', 'Log files older than this are automatically deleted');
print qq{</div>\n</div>\n};

# Section: Notifications
print qq{<div class="card bg-white shadow-sm border border-base-300 mb-6">\n<div class="card-body">\n};
print qq{<h2 class="card-title text-sm">Notifications</h2>\n};
field_text('NOTIFY_EMAIL', 'Email Address(es)', 'Comma-separated, empty = disabled');
field_select('NOTIFY_ON', 'Notify On', ['always', 'failure', 'never']);
print qq{</div>\n</div>\n};

# Section: SMTP Settings
print qq{<div class="card bg-white shadow-sm border border-base-300 mb-6">\n<div class="card-body">\n};
print qq{<h2 class="card-title text-sm">SMTP Settings</h2>\n};
print qq{<p class="text-xs text-base-content/60 mb-3">Optional. When SMTP Host is empty, system mail/sendmail is used.</p>\n};
field_text('SMTP_HOST', 'SMTP Host', 'e.g. smtp.gmail.com');
field_text('SMTP_PORT', 'SMTP Port', 'Default: 587');
field_text('SMTP_USER', 'SMTP Username', 'e.g. user@gmail.com');

# SMTP Password (type=password)
my $smtp_pw_val = Gniza4cpWHM::UI::esc($conf->{SMTP_PASSWORD} // '');
print qq{<div class="flex items-center gap-3 mb-2.5">\n};
print qq{  <label class="w-44 font-medium text-sm" for="SMTP_PASSWORD">SMTP Password</label>\n};
print qq{  <input type="password" class="input input-bordered input-sm w-full max-w-xs" id="SMTP_PASSWORD" name="SMTP_PASSWORD" value="$smtp_pw_val">\n};
print qq{</div>\n};

field_text('SMTP_FROM', 'From Address', 'Falls back to SMTP Username');
field_select('SMTP_SECURITY', 'Security', ['tls', 'ssl', 'none']);

print qq{<div class="flex gap-2 mt-3">\n};
print qq{  <button type="button" class="btn btn-secondary btn-sm" id="test-smtp-btn" onclick="gniza4cpTestSmtp()">Send Test Email</button>\n};
print qq{</div>\n};
print qq{<div id="gniza4cp-smtp-alert" class="mt-3"></div>\n};
print qq{</div>\n</div>\n};

# Section: User Restore (cPanel Plugin)
print qq{<div class="card bg-white shadow-sm border border-base-300 mb-6">\n<div class="card-body">\n};
print qq{<h2 class="card-title text-sm">User Restore (cPanel Plugin)</h2>\n};
print qq{<p class="text-xs text-base-content/60 mb-3">Controls which remotes are available for cPanel user self-service restore.</p>\n};
field_text('USER_RESTORE_REMOTES', 'Allowed Remotes', '"all" = all remotes, comma-separated names, empty = disabled', '', 'Which backup remotes cPanel users can restore from. Set to "all" for all remotes, specific names like "nas,offsite", or leave empty to disable user restore.');
print qq{</div>\n</div>\n};

# Section: Advanced
print qq{<div class="card bg-white shadow-sm border border-base-300 mb-6">\n<div class="card-body">\n};
print qq{<h2 class="card-title text-sm">Advanced</h2>\n};
field_text('LOCK_FILE', 'Lock File', 'Default: /var/run/gniza4cp.lock', '', 'Prevents multiple backup processes from running simultaneously');
field_text('SSH_TIMEOUT', 'SSH Timeout (seconds)', 'Default: 30', '', 'How long to wait for an SSH connection before giving up');
field_text('SSH_RETRIES', 'SSH Retries', 'Default: 3', '', 'Number of rsync retry attempts with exponential backoff on failure');
field_text('RSYNC_EXTRA_OPTS', 'Extra rsync Options', 'Additional flags for rsync', '', 'Global extra flags appended to all rsync commands, e.g. --compress');
print qq{</div>\n</div>\n};

# Submit
print qq{<div class="flex items-center gap-2 mt-4">\n};
print qq{  <button type="submit" class="btn btn-primary btn-sm">Save Settings</button>\n};
print qq{</div>\n};

print qq{</form>\n};

my $smtp_csrf = Gniza4cpWHM::UI::generate_csrf_token();
print qq{<script>\n};
print qq{var gniza4cpCsrf = '} . Gniza4cpWHM::UI::esc($smtp_csrf) . qq{';\n};
print <<'JS';
function gniza4cpTestSmtp() {
    var btn = document.getElementById('test-smtp-btn');
    var fd  = new FormData();
    fd.append('action', 'test_smtp');
    fd.append('gniza4cp_csrf', gniza4cpCsrf);
    fd.append('SMTP_HOST', document.getElementById('SMTP_HOST').value);
    fd.append('SMTP_PORT', document.getElementById('SMTP_PORT').value);
    fd.append('SMTP_USER', document.getElementById('SMTP_USER').value);
    fd.append('SMTP_PASSWORD', document.getElementById('SMTP_PASSWORD').value);
    fd.append('SMTP_FROM', document.getElementById('SMTP_FROM').value);
    fd.append('SMTP_SECURITY', document.getElementById('SMTP_SECURITY').value);
    fd.append('NOTIFY_EMAIL', document.getElementById('NOTIFY_EMAIL').value);

    var email = document.getElementById('NOTIFY_EMAIL').value;
    var host  = document.getElementById('SMTP_HOST').value;
    if (!host) { gniza4cpSmtpToast('error', 'SMTP Host is required.'); return; }
    if (!email) { gniza4cpSmtpToast('error', 'Notification email is required for test.'); return; }

    btn.disabled = true;
    btn.textContent = 'Sending\u2026';

    fetch('settings.cgi', { method: 'POST', body: fd })
        .then(function(r) { return r.json(); })
        .then(function(data) {
            if (data.csrf) {
                gniza4cpCsrf = data.csrf;
                var hf = document.querySelector('input[name="gniza4cp_csrf"]');
                if (hf) hf.value = data.csrf;
            }
            gniza4cpSmtpToast(data.success ? 'success' : 'error', data.message);
        })
        .catch(function(err) {
            gniza4cpSmtpToast('error', 'Request failed: ' + err.toString());
        })
        .finally(function() {
            btn.disabled = false;
            btn.textContent = 'Send Test Email';
        });
}

function gniza4cpSmtpToast(type, msg) {
    var area = document.getElementById('gniza4cp-smtp-alert');
    if (!area) return;
    area.innerHTML = '';
    var el = document.createElement('div');
    el.className = 'alert alert-' + type;
    el.className += ' px-5 py-3 rounded-lg text-sm';
    el.textContent = msg;
    area.appendChild(el);
    setTimeout(function() { el.style.opacity = '0'; }, type === 'error' ? 6000 : 3000);
    setTimeout(function() { area.innerHTML = ''; }, type === 'error' ? 6500 : 3500);
}
</script>
JS

print Gniza4cpWHM::UI::page_footer();
Whostmgr::HTMLInterface::footer();
