<script lang="ts">
  import SupportedDatetimePanel from '$lib/components/admin-settings/SupportedDatetimePanel.svelte';
  import SupportedVariablesPanel from '$lib/components/admin-settings/SupportedVariablesPanel.svelte';
  import SettingButtonsRow from '$lib/components/shared-components/settings/SystemConfigButtonRow.svelte';
  import SettingInputField from '$lib/components/shared-components/settings/setting-input-field.svelte';
  import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
  import { SettingInputFieldType } from '$lib/constants';
  import FormatMessage from '$lib/elements/FormatMessage.svelte';
  import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
  import { systemConfigManager } from '$lib/managers/system-config-manager.svelte';
  import { Route } from '$lib/route';
  import { handleSystemConfigSave } from '$lib/services/system-config.service';
  import { user } from '$lib/stores/user.store';
  import { getStorageTemplateOptions, type SystemConfigTemplateStorageOptionDto } from '@immich/sdk';
  import { Heading, Link, LoadingSpinner, Text } from '@immich/ui';
  import handlebar from 'handlebars';
  import * as luxon from 'luxon';
  import { onDestroy } from 'svelte';
  import { t } from 'svelte-i18n';
  import { createBubbler, preventDefault } from 'svelte/legacy';
  import { fade } from 'svelte/transition';

  type Props = {
    minified?: boolean;
    duration?: number;
    saveOnClose?: boolean;
  };

  const { minified = false, duration = 500, saveOnClose = false }: Props = $props();

  const disabled = $derived(featureFlagsManager.value.configFile);
  const config = $derived(systemConfigManager.value);
  let configToEdit = $state(systemConfigManager.cloneValue());

  const bubble = createBubbler();
  let templateOptions: SystemConfigTemplateStorageOptionDto | undefined = $state();
  let selectedPreset = $state('');

  const getTemplateOptions = async () => {
    templateOptions = await getStorageTemplateOptions();
    selectedPreset = config.storageTemplate.template;
  };

  const getSupportDateTimeFormat = () => getStorageTemplateOptions();

  const renderTemplate = (templateString: string) => {
    if (!templateOptions) {
      return '';
    }

    const template = handlebar.compile(templateString, {
      knownHelpers: undefined,
    });

    const substitutions: Record<string, string> = {
      filename: 'IMAGE_56437',
      ext: 'jpg',
      filetype: 'IMG',
      filetypefull: 'IMAGE',
      assetId: 'a8312960-e277-447d-b4ea-56717ccba856',
      assetIdShort: '56717ccba856',
      album: $t('album_name'),
      make: 'FUJIFILM',
      model: 'X-T50',
      lensModel: 'XF27mm F2.8 R WR',
    };

    const dt = luxon.DateTime.fromISO(new Date('2022-02-03T04:56:05.250').toISOString());
    const albumStartTime = luxon.DateTime.fromISO(new Date('2021-12-31T05:32:41.750').toISOString());
    const albumEndTime = luxon.DateTime.fromISO(new Date('2023-05-06T09:15:17.100').toISOString());

    const dateTokens = [
      ...templateOptions.yearOptions,
      ...templateOptions.monthOptions,
      ...templateOptions.weekOptions,
      ...templateOptions.dayOptions,
      ...templateOptions.hourOptions,
      ...templateOptions.minuteOptions,
      ...templateOptions.secondOptions,
    ];

    for (const token of dateTokens) {
      substitutions[token] = dt.toFormat(token);
      substitutions['album-startDate-' + token] = albumStartTime.toFormat(token);
      substitutions['album-endDate-' + token] = albumEndTime.toFormat(token);
    }

    return template(substitutions);
  };

  const handlePresetSelection = () => {
    configToEdit.storageTemplate.template = selectedPreset;
  };
  let parsedTemplate = $derived(() => {
    try {
      return renderTemplate(configToEdit.storageTemplate.template);
    } catch {
      return 'error';
    }
  });

  onDestroy(async () => {
    if (saveOnClose) {
      await handleSystemConfigSave({ storageTemplate: configToEdit.storageTemplate });
    }
  });
</script>

<section class="dark:text-immich-dark-fg mt-2">
  <div in:fade={{ duration }} class="mx-4 flex flex-col gap-4 py-4">
    <p class="text-sm dark:text-immich-dark-fg">
      <FormatMessage key="admin.storage_template_more_details">
        {#snippet children({ tag, message })}
          {#if tag === 'template-link'}
            <Link href="https://docs.immich.app/administration/storage-template">{message}</Link>
          {:else if tag === 'implications-link'}
            <Link href="https://docs.immich.app/administration/backup-and-restore#asset-types-and-storage-locations">
              {message}
            </Link>
          {/if}
        {/snippet}
      </FormatMessage>
    </p>
  </div>
  {#await getTemplateOptions() then}
    <div id="directory-path-builder" class="flex flex-col gap-4 {minified ? '' : 'ms-4 mt-4'}">
      <SettingSwitch
        title={$t('admin.storage_template_enable_description')}
        {disabled}
        bind:checked={configToEdit.storageTemplate.enabled}
        isEdited={!(configToEdit.storageTemplate.enabled === config.storageTemplate.enabled)}
      />

      {#if !minified}
        <SettingSwitch
          title={$t('admin.storage_template_hash_verification_enabled')}
          {disabled}
          subtitle={$t('admin.storage_template_hash_verification_enabled_description')}
          bind:checked={configToEdit.storageTemplate.hashVerificationEnabled}
          isEdited={!(
            configToEdit.storageTemplate.hashVerificationEnabled === config.storageTemplate.hashVerificationEnabled
          )}
        />
      {/if}

      {#if configToEdit.storageTemplate.enabled}
        <hr />

        <Heading size="tiny" color="primary">
          {$t('variables')}
        </Heading>

        <section class="support-date">
          {#await getSupportDateTimeFormat()}
            <LoadingSpinner />
          {:then options}
            <div transition:fade={{ duration: 200 }}>
              <SupportedDatetimePanel {options} />
            </div>
          {/await}
        </section>

        <section class="support-date">
          <SupportedVariablesPanel />
        </section>

        <div class="flex flex-col mt-2">
          <!-- <h3 class="text-base font-medium text-primary">{$t('template')}</h3> -->
          <Heading size="tiny" color="primary">
            {$t('template')}
          </Heading>

          <div class="my-2">
            <Text size="small">{$t('preview')}</Text>
          </div>

          <p class="text-sm">
            <FormatMessage
              key="admin.storage_template_path_length"
              values={{ length: parsedTemplate().length + $user.id.length + 'UPLOAD_LOCATION'.length, limit: 260 }}
            >
              {#snippet children({ message })}
                <span class="font-semibold text-primary">{message}</span>
              {/snippet}
            </FormatMessage>
          </p>

          <p class="text-sm">
            <FormatMessage key="admin.storage_template_user_label" values={{ label: $user.storageLabel || $user.id }}>
              {#snippet children({ message })}
                <code class="text-primary">{message}</code>
              {/snippet}
            </FormatMessage>
          </p>

          <p class="p-4 py-2 mt-2 text-xs bg-gray-200 rounded-lg dark:bg-gray-700 dark:text-immich-dark-fg">
            <span class="text-immich-fg/25 dark:text-immich-dark-fg/50"
              >UPLOAD_LOCATION/library/{$user.storageLabel || $user.id}</span
            >/{parsedTemplate()}.jpg
          </p>

          <form autocomplete="off" class="flex flex-col" onsubmit={preventDefault(bubble('submit'))}>
            <div class="flex flex-col my-2">
              {#if templateOptions}
                <label class="font-medium text-primary text-sm" for="preset-select">
                  {$t('preset')}
                </label>
                <select
                  class="immich-form-input p-2 mt-2 text-sm rounded-lg bg-slate-200 hover:cursor-pointer dark:bg-gray-600"
                  disabled={disabled || !configToEdit.storageTemplate.enabled}
                  name="presets"
                  id="preset-select"
                  bind:value={selectedPreset}
                  onchange={handlePresetSelection}
                >
                  {#each templateOptions.presetOptions as preset (preset)}
                    <option value={preset}>{renderTemplate(preset)}</option>
                  {/each}
                </select>
              {/if}
            </div>

            <div class="flex gap-2 align-bottom">
              <SettingInputField
                label={$t('template')}
                disabled={disabled || !configToEdit.storageTemplate.enabled}
                required
                inputType={SettingInputFieldType.TEXT}
                bind:value={configToEdit.storageTemplate.template}
                isEdited={!(configToEdit.storageTemplate.template === config.storageTemplate.template)}
              />

              <div class="flex-0">
                <SettingInputField
                  label={$t('extension')}
                  inputType={SettingInputFieldType.TEXT}
                  value=".jpg"
                  disabled
                />
              </div>
            </div>

            {#if !minified}
              <div id="migration-info" class="mt-2 text-sm">
                <Heading size="tiny" color="primary">
                  {$t('notes')}
                </Heading>
                <section class="flex flex-col gap-2">
                  <p>
                    <FormatMessage
                      key="admin.storage_template_migration_info"
                      values={{ job: $t('admin.storage_template_migration_job') }}
                    >
                      {#snippet children({ message })}
                        <a href={Route.queues()} class="text-primary">{message}</a>
                      {/snippet}
                    </FormatMessage>
                  </p>
                </section>
              </div>
            {/if}
          </form>
        </div>
      {/if}

      {#if !minified}
        <SettingButtonsRow bind:configToEdit keys={['storageTemplate']} {disabled} />
      {/if}
    </div>
  {/await}
</section>
