@Override
    public Mono<Theme> reloadTheme(String name) {
        return client.fetch(Theme.class, name)
            .flatMap(oldTheme -> {
                String settingName = oldTheme.getSpec().getSettingName();
                return waitForSettingDeleted(settingName)
                    .then(waitForAnnotationSettingsDeleted(name));
            })
            .then(Mono.defer(() -> {
                Path themePath = themeRoot.get().resolve(name);
                Path themeManifestPath = ThemeUtils.resolveThemeManifest(themePath);
                if (themeManifestPath == null) {
                    throw new IllegalArgumentException(
                        "The manifest file [theme.yaml] is required.");
                }
                Unstructured unstructured = loadThemeManifest(themeManifestPath);
                Theme newTheme = Unstructured.OBJECT_MAPPER.convertValue(unstructured,
                    Theme.class);
                return client.fetch(Theme.class, name)
                    .map(oldTheme -> {
                        newTheme.getMetadata().setVersion(oldTheme.getMetadata().getVersion());
                        return newTheme;
                    })
                    .flatMap(client::update);
            }))
            .flatMap(theme -> {
                String settingName = theme.getSpec().getSettingName();
                return Flux.fromIterable(ThemeUtils.loadThemeResources(getThemePath(theme)))
                    .filter(unstructured -> (Setting.KIND.equals(unstructured.getKind())
                        && unstructured.getMetadata().getName().equals(settingName))
                        || AnnotationSetting.KIND.equals(unstructured.getKind())
                    )
                    .doOnNext(unstructured -> populateThemeNameLabel(unstructured, name))
                    .flatMap(client::create)
                    .then(Mono.just(theme));
            });
    }
@Test
    void reloadThemeWhenSettingNameNotSetBefore() throws IOException {
        Theme theme = new Theme();
        theme.setMetadata(new Metadata());
        theme.getMetadata().setName("fake-theme");
        theme.setSpec(new Theme.ThemeSpec());
        theme.getSpec().setDisplayName("Hello");
        when(client.fetch(Theme.class, "fake-theme"))
            .thenReturn(Mono.just(theme));
        Setting setting = new Setting();
        setting.setMetadata(new Metadata());
        setting.setSpec(new Setting.SettingSpec());
        setting.getSpec().setForms(List.of());

        when(client.fetch(eq(Setting.class), eq(null))).thenReturn(Mono.empty());

        Path themeWorkDir = themeRoot.get().resolve(theme.getMetadata().getName());
        if (!Files.exists(themeWorkDir)) {
            Files.createDirectories(themeWorkDir);
        }
        Files.writeString(themeWorkDir.resolve("settings.yaml"), """
            apiVersion: v1alpha1
            kind: Setting
            metadata:
              name: fake-setting
            spec:
              forms:
                - group: sns
                  label: 社交资料
                  formSchema:
                    - $el: h1
                      children: Register
            """);

        Files.writeString(themeWorkDir.resolve("theme.yaml"), """
            apiVersion: v1alpha1
            kind: Theme
            metadata:
              name: fake-theme
            spec:
              displayName: Fake Theme
              settingName: fake-setting
            """);
        when(client.update(any(Theme.class)))
            .thenAnswer((Answer<Mono<Theme>>) invocation -> {
                Theme argument = invocation.getArgument(0);
                return Mono.just(argument);
            });

        when(client.create(any(Unstructured.class)))
            .thenAnswer((Answer<Mono<Unstructured>>) invocation -> {
                Unstructured argument = invocation.getArgument(0);
                JSONAssert.assertEquals("""
                        {
                           "spec": {
                             "forms": [
                               {
                                 "group": "sns",
                                 "label": "社交资料",
                                 "formSchema": [
                                   {
                                     "$el": "h1",
                                     "children": "Register"
                                   }
                                 ]
                               }
                             ]
                           },
                           "apiVersion": "v1alpha1",
                           "kind": "Setting",
                           "metadata": {
                              "name": "fake-setting",
                              "labels": {
                                  "theme.halo.run/theme-name": "fake-theme"
                              }
                            }
                         }
                        """,
                    JsonUtils.objectToJson(argument),
                    true);
                return Mono.just(invocation.getArgument(0));
            });

        when(client.list(eq(AnnotationSetting.class), any(), eq(null))).thenReturn(Flux.empty());

        themeService.reloadTheme("fake-theme")
            .as(StepVerifier::create)
            .consumeNextWith(themeUpdated -> {
                try {
                    JSONAssert.assertEquals("""
                            {
                                "spec": {
                                    "settingName": "fake-setting",
                                    "displayName": "Fake Theme",
                                    "version": "*",
                                    "requires": "*"
                                },
                                "apiVersion": "theme.halo.run/v1alpha1",
                                "kind": "Theme",
                                "metadata": {
                                    "name": "fake-theme"
                                }
                            }
                            """,
                        JsonUtils.objectToJson(themeUpdated),
                        true);
                } catch (JSONException e) {
                    throw new RuntimeException(e);
                }
            })
            .verifyComplete();
    }