package de.assecutor.pdftool.template;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;

/**
 * Verwaltet die Rechnungstemplates des Rechnungsgenerators in MongoDB
 * (Collection {@code invoice_templates}). Templates werden unter einem
 * eindeutigen Namen gespeichert; es können beliebig viele Templates
 * nebeneinander existieren. Die Verbindung wird über {@code MONGODB_URI}
 * in der .env-Datei konfiguriert.
 *
 * <p>Ein früher als Datei abgelegtes Template (~/.pdf-tool/rechnungstemplate.json)
 * wird beim ersten Zugriff einmalig als "{@value #DEFAULT_TEMPLATE_NAME}" in die
 * Datenbank übernommen.</p>
 */
@Service
public class InvoiceTemplateService {

    private static final Logger log = LoggerFactory.getLogger(InvoiceTemplateService.class);

    /** Name des Standard-Templates (Ziel der einmaligen Datei-Migration). */
    public static final String DEFAULT_TEMPLATE_NAME = "standard";

    private static final String LEGACY_TEMPLATE_FILE_NAME = "rechnungstemplate.json";

    private final InvoiceTemplateRepository repository;
    private final Path legacyTemplateFile;

    public InvoiceTemplateService(InvoiceTemplateRepository repository,
            @Value("${pdftool.template-dir:${user.home}/.pdf-tool}") String legacyTemplateDir) {
        this.repository = repository;
        this.legacyTemplateFile = Path.of(legacyTemplateDir, LEGACY_TEMPLATE_FILE_NAME);
    }

    /** Speichert das Template unter dem Namen (legt es an oder überschreibt das bestehende). */
    public void saveTemplate(String name, String templateData) {
        Optional<InvoiceTemplate> existing = repository.findByName(name);
        if (existing.isPresent()) {
            InvoiceTemplate template = existing.get();
            template.updateTemplate(templateData);
            repository.save(template);
        } else {
            repository.save(new InvoiceTemplate(name, templateData));
        }
    }

    /** @return true, wenn unter dem Namen bereits ein Template gespeichert ist. */
    public boolean templateExists(String name) {
        return repository.existsByName(name);
    }

    /** @return die Namen aller gespeicherten Templates, alphabetisch sortiert. */
    public List<String> templateNames() {
        migrateLegacyTemplateIfMissing();
        return repository.findAll().stream()
                .map(template -> template.getName())
                .sorted(String.CASE_INSENSITIVE_ORDER)
                .toList();
    }

    /** @return das gespeicherte Template mit dem Namen oder leer, wenn keines existiert. */
    public Optional<String> loadTemplate(String name) {
        if (DEFAULT_TEMPLATE_NAME.equals(name)) {
            migrateLegacyTemplateIfMissing();
        }
        return repository.findByName(name)
                .map(template -> template.getTemplateData())
                .filter(data -> !data.isBlank());
    }

    /**
     * Übernimmt das frühere Datei-Template einmalig als Standard-Template in die
     * Datenbank; die Datei bleibt als Sicherung unverändert liegen.
     */
    private void migrateLegacyTemplateIfMissing() {
        if (repository.existsByName(DEFAULT_TEMPLATE_NAME) || !Files.exists(legacyTemplateFile)) {
            return;
        }
        try {
            String data = Files.readString(legacyTemplateFile, StandardCharsets.UTF_8);
            if (data.isBlank()) {
                return;
            }
            saveTemplate(DEFAULT_TEMPLATE_NAME, data);
            log.info("Rechnungstemplate aus {} in die MongoDB übernommen.", legacyTemplateFile);
        } catch (IOException e) {
            log.warn("Altes Datei-Template {} konnte nicht gelesen werden: {}", legacyTemplateFile, e.getMessage());
        }
    }
}
