<script setup>

import { ref, useTemplateRef, watchEffect } from 'vue';
import { Dialog, TextInput, InputGroup, FormGroup, Button } from '@cloudron/pankow';
import { getTextFromFile } from '../utils.js';
import DomainsModel from '../models/DomainsModel.js';
import DomainProviderForm from './DomainProviderForm.vue';

const emit = defineEmits([ 'success' ]);

const domainsModel = DomainsModel.create();

const dialog = useTemplateRef('dialog');
const keyFileInput = useTemplateRef('keyFileInput');
const certificateFileInput = useTemplateRef('certificateFileInput');

const busy = ref(false);
const errorMessage = ref('');
const editing = ref(false);
const domain = ref('');
const zoneName = ref('');
const provider = ref('');
const tlsProvider = ref('letsencrypt-prod-wildcard');
const showAdvanced = ref(false);
const customNameservers = ref(false);
const certificateFileName = ref('');
const keyFileName = ref('');

const dnsConfig = ref(DomainsModel.createEmptyConfig());

const form = useTemplateRef('form');
const isFormValid = ref(false);
function checkValidity() {
  isFormValid.value = form.value ? form.value.checkValidity() : false;
}

async function onSubmit() {
  if (!form.value.reportValidity()) return;

  busy.value = true;
  errorMessage.value = '';

  const config = dnsConfig.value;
  config.customNameservers = customNameservers.value;

  const tlsConfig = {
    provider: tlsProvider.value,
    wildcard: false
  };

  // UI uses -wildcard providers, API uses wildcard flag
  if (tlsConfig.provider.indexOf('-wildcard') !== -1) {
    tlsConfig.provider = tlsConfig.provider.replace('-wildcard', '');
    tlsConfig.wildcard = true;
  }

  let fallbackCertificate = null;
  if (tlsConfig.provider === 'fallback') {
    const certFile = certificateFileInput.value.files[0] || null;
    const keyFile = keyFileInput.value.files[0] ||  null;

    if ((!certFile && keyFile) || (certFile && !keyFile)) {
      errorMessage.value = 'Both certificate and key file need to be provided';
      busy.value = false;
      return;
    } else if (certFile && keyFile) {
      fallbackCertificate = {
        cert: await getTextFromFile(certFile),
        key: await getTextFromFile(keyFile),
      };
    } else {
      // unchanged
    }
  }

  const func = editing.value ? domainsModel.update : domainsModel.add;
  const [error] = await func(domain.value, zoneName.value, provider.value, config, fallbackCertificate, tlsConfig);
  if (error) {
    errorMessage.value = error.body ? error.body.message : 'Internal error';
    busy.value = false;
    return console.error(error);
  }

  emit('success');
  dialog.value.close();
}

function onCertificateFileChange() {
  const file = certificateFileInput.value.files[0] || '';
  if (!file) return;

  certificateFileName.value = file ? file.name : '';
}

function onKeyFileChange() {
  const file = keyFileInput.value.files[0] || '';
  if (!file) return;

  keyFileName.value = file ? file.name : '';
}

watchEffect(() => {
  if (dnsConfig.value.credentials) setTimeout(checkValidity, 100);
});

defineExpose({
  open(d) {
    d = d ? JSON.parse(JSON.stringify(d)) : { config: {}, tlsConfig: { provider: 'letsencrypt-prod', wildcard: true } }; // make a copy

    provider.value = d.provider || '';
    dnsConfig.value = d.config;
    if (d.tlsConfig.wildcard) {
      tlsProvider.value = d.tlsConfig.provider + '-wildcard';
    } else {
      tlsProvider.value = d.tlsConfig.provider;
    }

    busy.value = false;
    showAdvanced.value = false;
    errorMessage.value = '';
    editing.value = !!d.domain;
    domain.value = d.domain || '';
    zoneName.value = d.zoneName || '';
    customNameservers.value = d.config.customNameservers;
    certificateFileName.value = d.tlsConfig?.provider === 'fallback' ? String.fromCharCode(0x25CF).repeat(8) : '';
    keyFileName.value = d.tlsConfig?.provider === 'fallback' ? String.fromCharCode(0x25CF).repeat(8) : '';

    dialog.value.open();

    setTimeout(checkValidity, 100); // update state of the confirm button
  }
});

</script>

<template>
  <Dialog ref="dialog"
    :title="editing ? $t('domains.domainDialog.editTitle') : $t('domains.domainDialog.addTitle')"
    :confirm-busy="busy"
    :confirm-active="!busy && isFormValid"
    :confirm-label="editing ? $t('main.dialog.save') : $t('main.action.add')"
    :reject-label="$t('main.dialog.cancel')"
    :reject-active="!busy"
     reject-style="secondary"
    @confirm="onSubmit()"
  >
    <form ref="form" @submit.prevent="onSubmit()" autocomplete="off" @input="checkValidity()">
      <fieldset :disabled="busy">
        <input style="display: none;" type="submit" :disabled="busy"/>

        <div class="error-label" v-show="errorMessage">{{ errorMessage }}</div>

        <FormGroup>
          <label for="domainInput">{{ $t('domains.domainDialog.domain') }}</label>
          <TextInput id="domainInput" v-model="domain" placeholder="example.com" :readonly="editing" :required="!editing" />
        </FormGroup>

        <DomainProviderForm v-model:provider="provider" v-model:dns-config="dnsConfig" v-model:tls-provider="tlsProvider" v-model:zone-name="zoneName" v-model:custom-nameservers="customNameservers" :domain="domain" :show-advanced="showAdvanced" />

        <div v-show="showAdvanced">
          <div v-if="tlsProvider === 'fallback'">
            <label>{{ $t('domains.domainDialog.fallbackCertCustomCert') }}</label>
            <div description v-html="$t('domains.domainDialog.fallbackCertCustomCertInfo', { customCertLink: 'https://docs.cloudron.io/certificates/#custom-certificates' })"></div>
          </div>

          <div v-if="tlsProvider === 'fallback'">
            <input type="file" ref="certificateFileInput" style="display: none" @change="onCertificateFileChange"/>
            <input type="file" ref="keyFileInput" style="display: none" @change="onKeyFileChange"/>

            <div style="display: grid; grid-template-columns: auto 1fr; gap: 5px 10px; margin-top: 15px">
              <label>{{ $t('domains.domainDialog.fallbackCertCertificatePlaceholder') }}</label>
              <InputGroup>
                <TextInput v-model="certificateFileName" @click="certificateFileInput.click()" style="cursor: pointer; flex-grow: 1;" :disabled="busy" />
                <Button tool secondary icon="fa-solid fa-upload" @click="certificateFileInput.click()"></Button>
              </InputGroup>
              <label>{{ $t('domains.domainDialog.fallbackCertKeyPlaceholder') }}</label>
              <InputGroup>
                <TextInput v-model="keyFileName" @click="keyFileInput.click()" style="cursor: pointer; flex-grow: 1;" :disabled="busy" />
                <Button tool secondary icon="fa-solid fa-upload" @click="keyFileInput.click()"></Button>
              </InputGroup>
            </div>
          </div>
        </div>

        <div v-if="!showAdvanced" style="margin-top: 15px" class="actionable" @click="showAdvanced = true">{{ $t('domains.domainDialog.advancedAction') }}</div>
      </fieldset>
    </form>
  </Dialog>
</template>