<script setup>

import { useI18n } from 'vue-i18n';
const i18n = useI18n();
const t = i18n.t;

import { ref } from 'vue';
import { TextInput, InputGroup, MaskedInput, Button, FormGroup, Checkbox, SingleSelect } from '@cloudron/pankow';
import { ENDPOINTS_OVH } from '../constants.js';
import DomainsModel from '../models/DomainsModel.js';

defineProps({
  domain: {
    type: String,
    default: '',
  },
  showAdvanced: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
});

const provider = defineModel('provider');
const dnsConfig = defineModel('dnsConfig');
const tlsProvider = defineModel('tlsProvider');
const zoneName = defineModel('zoneName');
const customNameservers = defineModel('customNameservers');

const tlsProviders = [
  { name: 'Let\'s Encrypt Prod', value: 'letsencrypt-prod' },
  { name: 'Let\'s Encrypt Prod - Wildcard', value: 'letsencrypt-prod-wildcard' },
  { name: 'Let\'s Encrypt Staging', value: 'letsencrypt-staging' },
  { name: 'Let\'s Encrypt Staging - Wildcard', value: 'letsencrypt-staging-wildcard' },
  { name: 'Self-Signed', value: 'fallback' }, // this is not 'Custom' because we don't allow user to upload certs during setup phase
];

const gandiTokenTypes = [
  { name: t('domains.domainDialog.gandiTokenTypeApiKey'), value: 'ApiKey' },
  { name: t('domains.domainDialog.gandiTokenTypePAT'), value: 'PAT' },
];

const cloudflareTokenTypes = [
  { name: t('domains.domainDialog.cloudflareTokenTypeGlobalApiKey'), value: 'GlobalApiKey' },
  { name: t('domains.domainDialog.cloudflareTokenTypeApiToken'), value: 'ApiToken' },
];

function needsPort80(dnsProvider, tlsProvider) {
  return ((dnsProvider === 'manual' || dnsProvider === 'noop' || dnsProvider === 'wildcard') &&
    (tlsProvider === 'letsencrypt-prod' || tlsProvider === 'letsencrypt-staging'));
}

function resetFields() {
  dnsConfig.value.accessKeyId = '';
  dnsConfig.value.accessKey = '';
  dnsConfig.value.accessToken = '';
  dnsConfig.value.apiKey = '';
  dnsConfig.value.appKey = '';
  dnsConfig.value.appSecret = '';
  dnsConfig.value.apiPassword = '';
  dnsConfig.value.apiSecret = '';
  dnsConfig.value.consumerKey = '';
  dnsConfig.value.credentials = { client_email: '', private_key: '' };
  dnsConfig.value.customerNumber = '';
  dnsConfig.value.defaultProxyStatus = false;
  dnsConfig.value.email = '';
  dnsConfig.value.endpoint = '';
  dnsConfig.value.password = '';
  dnsConfig.value.projectId = '';
  dnsConfig.value.secretAccessKey = '';
  dnsConfig.value.secretapikey = '';
  dnsConfig.value.token = '';
  dnsConfig.value.tokenType = '';
  dnsConfig.value.username = '';
}

function onProviderChange(p) {
  resetFields();

  // wildcard LE won't work without automated DNS
  if (p === 'manual' || p === 'noop' || p === 'wildcard') {
    tlsProvider.value = 'letsencrypt-prod';
  } else {
    tlsProvider.value = 'letsencrypt-prod-wildcard';
  }
}

const gcdnsFileParseError = ref('');
function onGcdnsFileInputChange(event) {
  gcdnsFileParseError.value = '';

  const fr = new FileReader();

  fr.onload = () => {
    // validate input file
    try {
      const keyJson = JSON.parse(fr.result);
      if (!keyJson.project_id) throw new Error('project_id field missing in JSON key file');
      if (!keyJson.client_email) throw new Error('client_email field missing in JSON key file');
      if (!keyJson.private_key) throw new Error('private_key field missing in JSON key file');

      dnsConfig.value.projectId = keyJson.project_id;
      dnsConfig.value.credentials = {
        client_email: keyJson.client_email,
        private_key: keyJson.private_key,
      };
    } catch (e) {
      if (e.name === 'SyntaxError') gcdnsFileParseError.value = 'Invalid JSON';
      else gcdnsFileParseError.value = e.message;

      dnsConfig.value.projectId = '';
      dnsConfig.value.credentials = {
        client_email: '',
        private_key: '',
      };
    }
  };
  fr.readAsText(event.target.files[0]);
}

</script>

<template>
  <div>
    <FormGroup>
      <label for="providerInput">{{ $t('domains.domainDialog.provider') }} <sup><a href="https://docs.cloudron.io/domains/#dns-providers" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
      <SingleSelect v-model="provider" :disabled="disabled" :options="DomainsModel.providers" option-key="value" option-label="name" required @select="onProviderChange"/>
    </FormGroup>

    <div class="warning-label" v-show="provider === 'wildcard'" v-html="$t('domains.domainDialog.wildcardInfo', { domain: domain })"></div>
    <div class="warning-label" v-show="provider === 'manual'" v-html="$t('domains.domainDialog.manualInfo')"></div>
    <div class="warning-label" v-show="needsPort80(provider, tlsProvider)" v-html="$t('domains.domainDialog.letsEncryptInfo')"></div>

    <!-- Route53 -->
    <FormGroup v-if="provider === 'route53'">
      <label for="accessKeyIdInput">{{ $t('domains.domainDialog.route53AccessKeyId') }}</label>
      <TextInput id="accessKeyIdInput" v-model="dnsConfig.accessKeyId" minlength="16" maxlength="32" required />
    </FormGroup>
    <FormGroup v-if="provider === 'route53'">
      <label for="secretAccessKeyInput">{{ $t('domains.domainDialog.route53SecretAccessKey') }}</label>
      <MaskedInput id="secretAccessKeyInput" v-model="dnsConfig.secretAccessKey" required />
    </FormGroup>

    <!-- Google Cloud DNS -->
    <FormGroup v-if="provider === 'gcdns'">
      <input type="file" id="gcdnsKeyFileInput" style="display:none" accept="application/json, text/json" @change="onGcdnsFileInputChange"/>
      <label class="control-label">{{ $t('domains.domainDialog.gcdnsServiceAccountKey') }}{{ dnsConfig.projectId ? ` - project: ${dnsConfig.projectId}` : '' }}</label>
      <InputGroup>
        <input style="display: none" :value="dnsConfig.credentials.client_email" required /> <!-- for form validation -->
        <TextInput readonly style="cursor: pointer; flex-grow: 1" v-model="dnsConfig.credentials.client_email" placeholder="Service account key" onclick="getElementById('gcdnsKeyFileInput').click();"/>
        <Button tool icon="fa fa-upload" onclick="document.getElementById('gcdnsKeyFileInput').click();"/>
      </InputGroup>
      <div class="error-label" v-show="gcdnsFileParseError">{{ gcdnsFileParseError }}</div>
    </FormGroup>

    <!-- DigitalOcean -->
    <FormGroup v-if="provider === 'digitalocean'">
      <label for="digitalOceanTokenInput">{{ $t('domains.domainDialog.digitalOceanToken') }}</label>
      <MaskedInput id="digitalOceanTokenInput" v-model="dnsConfig.token" required />
    </FormGroup>

    <!-- Gandi -->
    <FormGroup v-if="provider === 'gandi'">
      <label for="gandiTokenTypeInput">{{ $t('domains.domainDialog.gandiTokenType') }}</label>
      <SingleSelect v-model="dnsConfig.tokenType" :options="gandiTokenTypes" option-key="value" option-label="name" />
    </FormGroup>
    <FormGroup v-if="provider === 'gandi'">
      <label for="gandiApiKeyInput">{{ $t('domains.domainDialog.gandiApiKey') }}</label>
      <MaskedInput id="gandiApiKeyInput" v-model="dnsConfig.token" required />
    </FormGroup>

    <!-- GoDaddy -->
    <FormGroup v-if="provider === 'godaddy'">
      <label for="godaddyApiKeyInput">{{ $t('domains.domainDialog.goDaddyApiKey') }}</label>
      <TextInput id="godaddyApiKeyInput" v-model="dnsConfig.apiKey" minlength="1" required />
    </FormGroup>
    <FormGroup v-if="provider === 'godaddy'">
      <label for="godaddyApiSecretInput">{{ $t('domains.domainDialog.goDaddyApiSecret') }}</label>
      <MaskedInput for="godaddyApiSecretInput" v-model="dnsConfig.apiSecret" required />
    </FormGroup>

    <!-- Netcup -->
    <FormGroup v-if="provider === 'netcup'">
      <label for="netcupCustomerNumberInput">{{ $t('domains.domainDialog.netcupCustomerNumber') }}</label>
      <TextInput id="netcupCustomerNumberInput" v-model="dnsConfig.customerNumber" required />
    </FormGroup>
    <FormGroup v-if="provider === 'netcup'">
      <label for="netcupApiKeyInput">{{ $t('domains.domainDialog.netcupApiKey') }}</label>
      <TextInput id="netcupApiKeyInput" v-model="dnsConfig.apiKey" minlength="1" required />
    </FormGroup>
    <FormGroup v-if="provider === 'netcup'">
      <label for="netcupApiPasswordInput">{{ $t('domains.domainDialog.netcupApiPassword') }}</label>
      <MaskedInput id="netcupApiPasswordInput" v-model="dnsConfig.apiPassword" required />
    </FormGroup>

    <!-- OVH -->
    <FormGroup v-if="provider === 'ovh'">
      <label for="ovhEndpointInput">{{ $t('domains.domainDialog.ovhEndpoint') }}</label>
      <SingleSelect id="ovhEndpointInput" v-model="dnsConfig.endpoint" :options="ENDPOINTS_OVH" option-key="value" option-label="name" />
    </FormGroup>
    <FormGroup v-if="provider === 'ovh'">
      <label for="ovhConsumerKeyInput">{{ $t('domains.domainDialog.ovhConsumerKey') }}</label>
      <TextInput id="ovhConsumerKeyInput" v-model="dnsConfig.consumerKey" required />
    </FormGroup>
    <FormGroup v-if="provider === 'ovh'">
      <label for="ovhAppKeyInput">{{ $t('domains.domainDialog.ovhAppKey') }}</label>
      <TextInput id="ovhAppKeyInput" v-model="dnsConfig.appKey" minlength="1" required />
    </FormGroup>
    <FormGroup v-if="provider === 'ovh'">
      <label for="ovhAppSecretInput">{{ $t('domains.domainDialog.ovhAppSecret') }}</label>
      <MaskedInput id="ovhAppSecretInput" v-model="dnsConfig.appSecret" required />
    </FormGroup>

    <!-- Porkbun -->
    <FormGroup v-if="provider === 'porkbun'">
      <label for="porkbunApikeyInput">{{ $t('domains.domainDialog.porkbunApikey') }}</label>
      <TextInput id="porkbunApikeyInput" v-model="dnsConfig.apikey" minlength="1" required />
    </FormGroup>
    <FormGroup v-if="provider === 'porkbun'">
      <label for="porkbunSecretapikeyInput">{{ $t('domains.domainDialog.porkbunSecretapikey') }}</label>
      <MaskedInput id="porkbunSecretapikeyInput" v-model="dnsConfig.secretapikey" required />
    </FormGroup>

    <!-- Cloudflare -->
    <FormGroup v-if="provider === 'cloudflare'">
      <label for="cloudflareTokenTypeInput">{{ $t('domains.domainDialog.cloudflareTokenType') }}</label>
      <SingleSelect v-model="dnsConfig.tokenType" :options="cloudflareTokenTypes" option-key="value" option-label="name" required/>
    </FormGroup>
    <FormGroup v-if="provider === 'cloudflare' && dnsConfig.tokenType === 'GlobalApiKey' || dnsConfig.tokenType === 'ApiToken'">
      <label for="cloudflareTokenInput" v-show="dnsConfig.tokenType === 'GlobalApiKey'">{{ $t('domains.domainDialog.cloudflareTokenTypeGlobalApiKey') }}</label>
      <label for="cloudflareTokenInput" v-show="dnsConfig.tokenType === 'ApiToken'">{{ $t('domains.domainDialog.cloudflareTokenTypeApiToken') }}</label>
      <MaskedInput id="cloudflareTokenInput" v-model="dnsConfig.token" required />
    </FormGroup>
    <FormGroup v-if="provider === 'cloudflare' && dnsConfig.tokenType === 'GlobalApiKey'">
      <label for="cloudflareEmailInput">{{ $t('domains.domainDialog.cloudflareEmail') }}</label>
      <TextInput id="cloudflareEmailInput" type="email" v-model="dnsConfig.email" required />
    </FormGroup>
    <div v-if="provider === 'cloudflare'">
      <Checkbox v-model="dnsConfig.defaultProxyStatus" :label="$t('domains.domainDialog.cloudflareDefaultProxyStatus')" help-url="https://docs.cloudron.io/domains/#cloudflare-dns" />
    </div>

    <!-- Linode -->
    <FormGroup v-if="provider === 'linode'">
      <label for="linodeTokenInput">{{ $t('domains.domainDialog.linodeToken') }}</label>
      <MaskedInput id="linodeTokenInput" v-model="dnsConfig.token" required />
    </FormGroup>

    <!-- Bunny -->
    <FormGroup v-if="provider === 'bunny'">
      <label for="bunnyAccessKeyInput">{{ $t('domains.domainDialog.bunnyAccessKey') }}</label>
      <MaskedInput id="bunnyAccessKeyInput" v-model="dnsConfig.accessKey" required />
    </FormGroup>

    <!-- dnsimple -->
    <FormGroup v-if="provider === 'dnsimple'">
      <label for="dnsimpleAccessTokenInput">{{ $t('domains.domainDialog.dnsimpleAccessToken') }}</label>
      <MaskedInput id="dnsimpleAccessTokenInput" v-model="dnsConfig.accessToken" required />
    </FormGroup>

    <!-- Hetzner -->
    <FormGroup v-if="provider === 'hetzner' || provider === 'hetznercloud'">
      <label for="hetznerTokenInput">{{ $t('domains.domainDialog.hetznerToken') }}</label>
      <MaskedInput id="hetznerTokenInput" v-model="dnsConfig.token" required />
    </FormGroup>

    <!-- Vultr -->
    <FormGroup v-if="provider === 'vultr'">
      <label for="vultrTokenInput">{{ $t('domains.domainDialog.vultrToken') }}</label>
      <MaskedInput id="vultrTokenInput" v-model="dnsConfig.token" required />
    </FormGroup>

    <!-- deSEC -->
    <FormGroup v-if="provider === 'desec'">
      <label for="deSecTokenInput">{{ $t('domains.domainDialog.deSecToken') }}</label>
      <MaskedInput id="deSecTokenInput" v-model="dnsConfig.token" required />
    </FormGroup>

    <!-- Name.com -->
    <FormGroup v-if="provider === 'namecom'">
      <label for="nameComUsernameInput">{{ $t('domains.domainDialog.nameComUsername') }}</label>
      <TextInput id="nameComUsernameInput" v-model="dnsConfig.username" required />
    </FormGroup>
    <FormGroup v-if="provider === 'namecom'">
      <label for="nameComTokenInput">{{ $t('domains.domainDialog.nameComApiToken') }}</label>
      <MaskedInput id="nameComTokenInput" v-model="dnsConfig.token" required />
    </FormGroup>

    <!-- Namecheap -->
    <FormGroup v-if="provider === 'namecheap'">
      <label for="namecheapUsernameInput">{{ $t('domains.domainDialog.namecheapUsername') }}</label>
      <TextInput id="namecheapUsernameInput" v-model="dnsConfig.username" required />
    </FormGroup>
    <FormGroup v-if="provider === 'namecheap'">
      <label for="namecheapApiKeyInput">{{ $t('domains.domainDialog.namecheapApiKey') }}</label>
      <MaskedInput id="namecheapApiKeyInput" v-model="dnsConfig.token" required />
      <div class="warning-label" v-if="provider === 'namecheap'" v-html="$t('domains.domainDialog.namecheapInfo')"></div>
    </FormGroup>

    <!-- INWX -->
    <FormGroup v-if="provider === 'inwx'">
      <label for="inwxUsernameInput">{{ $t('domains.domainDialog.inwxUsername') }}</label>
      <TextInput id="inwxUsernameInput" v-model="dnsConfig.username" required />
    </FormGroup>
    <FormGroup v-if="provider === 'inwx'">
      <label for="inwxPasswordInput">{{ $t('domains.domainDialog.inwxPassword') }}</label>
      <MaskedInput id="inwxPasswordInput" v-model="dnsConfig.password" required />
    </FormGroup>

    <FormGroup v-if="showAdvanced">
      <label for="zoneNameInput">{{ $t('domains.domainDialog.zoneName') }} <sup><a href="https://docs.cloudron.io/domains/#zone-name" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
      <TextInput id="zoneNameInput" v-model="zoneName" />
      <small class="helper-text">{{ $t('domains.domainDialog.zoneNamePlaceholder') }}</small>
    </FormGroup>


    <Checkbox v-if="showAdvanced" v-model="customNameservers" :label="$t('domains.domainDialog.customNameservers')" />

    <FormGroup v-if="showAdvanced">
      <label>Certificate provider <sup><a href="https://docs.cloudron.io/certificates/#certificate-providers" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
      <SingleSelect v-model="tlsProvider" :options="tlsProviders" option-key="value" option-label="name" required/>
    </FormGroup>

  </div>
</template>
