package com.easyagents.spring.boot.autoconfigure;

import com.easyagents.document.core.DocumentParseService;
import com.easyagents.document.core.entity.ParseRequest;
import com.easyagents.document.core.entity.ParseResponse;
import com.easyagents.document.core.entity.ParseTaskInfo;
import com.easyagents.document.core.entity.ParseTaskStatus;
import com.easyagents.document.pdf.PdfDocumentParseService;
import com.easyagents.document.pptx.PptxDocumentParseService;
import com.easyagents.document.xlsx.XlsxDocumentParseService;
import com.easyagents.llm.ollama.OllamaChatModel;
import com.easyagents.spring.boot.document.pptx.MineruPptxAutoConfiguration;
import com.easyagents.spring.boot.document.pdf.mineru.MineruPdfAutoConfiguration;
import com.easyagents.spring.boot.document.xlsx.MineruXlsxAutoConfiguration;
import com.easyagents.spring.boot.llm.ollama.OllamaAutoConfiguration;
import com.easyagents.spring.boot.rag.ingestion.RagIngestionAutoConfiguration;
import com.easyagents.spring.boot.store.opensearch.OpenSearchAutoConfiguration;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

public class StarterConditionalAutoConfigurationTest {

    private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
        .withUserConfiguration(
            RagIngestionAutoConfiguration.class,
            OllamaAutoConfiguration.class,
            OpenSearchAutoConfiguration.class,
            MineruPdfAutoConfiguration.class,
            MineruPptxAutoConfiguration.class,
            MineruXlsxAutoConfiguration.class
        );

    @Test
    public void shouldNotCreateOptionalBeansWithoutExplicitProperties() {
        contextRunner.run(context -> {
            Assert.assertTrue(context.containsBean("ragIngestionService"));
            Assert.assertFalse(context.containsBean("ollamaLlm"));
            Assert.assertFalse(context.containsBean("openSearchVectorStore"));
            Assert.assertFalse(context.containsBean("pdfDocumentParseService"));
            Assert.assertFalse(context.containsBean("documentParseService"));
        });
    }

    @Test
    public void shouldCreateOllamaBeanWhenModelConfigured() {
        contextRunner
            .withPropertyValues("easy-agents.llm.ollama.model=qwen3:8b")
            .run(context -> Assert.assertNotNull(context.getBean(OllamaChatModel.class)));
    }

    @Test
    public void shouldCreateMineruDocumentBeansWhenConfigured() {
        contextRunner
            .withPropertyValues(
                "easy-agents.document.ocr.provider=mineru",
                "easy-agents.document.ocr.mineru.base-url=https://hub.wust.edu.cn/modelServer/mineru-api"
            )
            .run(context -> {
                Assert.assertNotNull(context.getBean(PdfDocumentParseService.class));
                Assert.assertNotNull(context.getBean(PptxDocumentParseService.class));
                Assert.assertNotNull(context.getBean(XlsxDocumentParseService.class));
                Assert.assertNotNull(context.getBean(DocumentParseService.class));
            });
    }

    @Test
    public void shouldCreatePptxAndXlsxBeansWhenMineruOcrConfigured() {
        contextRunner
            .withPropertyValues(
                "easy-agents.document.ocr.provider=mineru",
                "easy-agents.document.ocr.mineru.base-url=https://hub.wust.edu.cn/modelServer/mineru-api"
            )
            .run(context -> {
                Assert.assertNotNull(context.getBean(PptxDocumentParseService.class));
                Assert.assertNotNull(context.getBean(XlsxDocumentParseService.class));
                Assert.assertNotNull(context.getBean(DocumentParseService.class));
            });
    }

    @Test
    public void shouldKeepPdfAsDefaultDocumentParseServiceWhenMineruOcrConfigured() {
        contextRunner
            .withPropertyValues(
                "easy-agents.document.ocr.provider=mineru",
                "easy-agents.document.ocr.mineru.base-url=https://hub.wust.edu.cn/modelServer/mineru-api"
            )
            .run(context -> {
                PdfDocumentParseService pdfService = context.getBean(PdfDocumentParseService.class);
                Assert.assertNotNull(pdfService);
                Assert.assertNotNull(context.getBean(PptxDocumentParseService.class));
                Assert.assertNotNull(context.getBean(XlsxDocumentParseService.class));
                Assert.assertSame(pdfService, context.getBean("documentParseService"));
                Assert.assertSame(pdfService, context.getBean(DocumentParseService.class));
            });
    }

    @Test
    public void shouldAliasCustomNamedPdfServiceAsDefaultDocumentParseService() {
        new ApplicationContextRunner()
            .withUserConfiguration(CustomPdfParseServiceConfiguration.class)
            .withUserConfiguration(
                RagIngestionAutoConfiguration.class,
                OllamaAutoConfiguration.class,
                OpenSearchAutoConfiguration.class,
                MineruPdfAutoConfiguration.class,
                MineruPptxAutoConfiguration.class,
                MineruXlsxAutoConfiguration.class
            )
            .withPropertyValues(
                "easy-agents.document.ocr.provider=mineru",
                "easy-agents.document.ocr.mineru.base-url=https://hub.wust.edu.cn/modelServer/mineru-api"
            )
            .run(context -> {
                PdfDocumentParseService pdfService = context.getBean(PdfDocumentParseService.class);
                Assert.assertSame(pdfService, context.getBean("documentParseService"));
                Assert.assertSame(pdfService, context.getBean(DocumentParseService.class));
            });
    }

    @Configuration(proxyBeanMethods = false)
    static class CustomPdfParseServiceConfiguration {

        @Bean("customPdfService")
        PdfDocumentParseService customPdfService() {
            return new NoopPdfDocumentParseService();
        }
    }

    static class NoopPdfDocumentParseService implements PdfDocumentParseService {

        @Override
        public ParseResponse parse(ParseRequest request) {
            return new ParseResponse();
        }

        @Override
        public ParseTaskStatus submit(ParseRequest request) {
            return new ParseTaskStatus();
        }

        @Override
        public ParseTaskStatus queryTask(String taskId) {
            return new ParseTaskStatus();
        }

        @Override
        public ParseResponse queryResult(String taskId) {
            return new ParseResponse();
        }

        @Override
        public ParseTaskInfo queryTaskInfo(String taskId) {
            return new ParseTaskInfo();
        }
    }
}
