package com.interplug.qcast.batch.master;

import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.transaction.PlatformTransactionManager;
import com.interplug.qcast.biz.displayItem.DisplayItemService;
import com.interplug.qcast.biz.displayItem.dto.DisplayItemRequest;
import com.interplug.qcast.biz.specialNote.SpecialNoteService;
import com.interplug.qcast.biz.specialNote.dto.SpecialNoteItemRequest;
import com.interplug.qcast.biz.specialNote.dto.SpecialNoteRequest;
import com.interplug.qcast.biz.specialNote.dto.SpecialNoteSyncResponse;
import com.interplug.qcast.util.InterfaceQsp;
import lombok.extern.slf4j.Slf4j;

@Configuration
@Slf4j
public class SpecialNoteDispItemJobConfiguration implements JobExecutionListener {

  private final InterfaceQsp interfaceQsp;

  private final SpecialNoteService specialNoteService;
  private final DisplayItemService displayItemService;

  @Value("${qsp.master-special-note-disp-item-batch-url}")
  private String qspMasterSpecialNoteDispItemBatchUrl;

  private SpecialNoteSyncResponse SpecialNoteDispItemSyncResponse;

  public SpecialNoteDispItemJobConfiguration(InterfaceQsp interfaceQsp,
      SpecialNoteService specialNoteService, DisplayItemService displayItemService) {
    this.interfaceQsp = interfaceQsp;
    this.specialNoteService = specialNoteService;
    this.displayItemService = displayItemService;
  }

  @Override
  public void beforeJob(JobExecution jobExecution) {
    log.info("Job 시작: 초기화 메서드 호출 중...");
    try {
      this.SpecialNoteDispItemSyncResponse = interfaceQsp.callApiData(HttpMethod.GET,
          qspMasterSpecialNoteDispItemBatchUrl, null, SpecialNoteSyncResponse.class);
      log.info("API 호출 완료, 항목 수: {}",
          this.SpecialNoteDispItemSyncResponse.getSdOrderSpnList().size());
    } catch (Exception e) {
      log.error("specialNoteDispItemSyncResponse 갱신 중 오류: {}", e.getMessage());
    }
  }

  @Bean
  public Job specialNoteDispItemAdditionalJob(JobRepository jobRepository, Step specialNoteStep,
      Step specialNoteItemStep, Step storeDispItemStep) {
    return new JobBuilder("specialNoteDispItemAdditionalJob", jobRepository).start(specialNoteStep)
        .next(specialNoteItemStep).next(storeDispItemStep).listener(this).build();
  }

  private <T> Step buildStep(String stepName, JobRepository jobRepository,
      PlatformTransactionManager transactionManager, ItemReader<T> reader, ItemWriter<T> writer) {
    return new StepBuilder(stepName, jobRepository).<T, T>chunk(10, transactionManager)
        .reader(reader).writer(writer).build();
  }

  @Bean
  public Step specialNoteStep(JobRepository jobRepository,
      PlatformTransactionManager transactionManager) {
    return buildStep("specialNoteStep", jobRepository, transactionManager, specialNoteListReader(),
        createWriter((items) -> {
          try {
            log.debug("Special Note batch processing {} items", items.size());
            specialNoteService.setSpecialNoteBatch(items);
            log.debug("Successfully processed Special Note batch");
          } catch (Exception e) {
            log.error("Error processing Special Note batch: {}", e.getMessage(), e);
            throw new RuntimeException("Failed to process Special Note batch", e);
          }
        }, "specialNote"));
  }

  @Bean
  public Step specialNoteItemStep(JobRepository jobRepository,
      PlatformTransactionManager transactionManager) {
    return buildStep("specialNoteItemStep", jobRepository, transactionManager,
        specialNoteItemListReader(), createWriter((items) -> {
          try {
            log.debug("Special Note Item batch processing {} items", items.size());
            specialNoteService.setSpecialNoteItemBatch(items);
            log.debug("Successfully processed Special Note Item batch");
          } catch (Exception e) {
            log.error("Error processing Special Note Item batch: {}", e.getMessage(), e);
            throw new RuntimeException("Failed to process Special Note Item batch", e);
          }
        }, "specialNoteItem"));
  }

  @Bean
  public Step storeDispItemStep(JobRepository jobRepository,
      PlatformTransactionManager transactionManager) {
    return buildStep("storeDispItemStep", jobRepository, transactionManager,
        storeDispItemListReader(), createWriter((items) -> {
          try {
            log.debug("Store Disp Item batch processing {} items", items.size());
            displayItemService.setStoreDispItemBatch(items);
            log.debug("Successfully processed Store Disp Item batch");
          } catch (Exception e) {
            log.error("Error processing Store Disp Item batch: {}", e.getMessage(), e);
            throw new RuntimeException("Failed to process Store Disp Item batch", e);
          }
        }, "storeDispItem"));
  }

  private <T> ListItemReader<T> createReader(List<T> items, String readerName) {
    log.info("{}Reader 호출됨...", readerName);
    return new ListItemReader<>(items != null ? items : Collections.emptyList());
  }

  @Bean
  @StepScope
  public ListItemReader<SpecialNoteRequest> specialNoteListReader() {
    return createReader(SpecialNoteDispItemSyncResponse != null
        ? SpecialNoteDispItemSyncResponse.getSdOrderSpnList()
        : null, "specialNote");
  }

  @Bean
  @StepScope
  public ListItemReader<SpecialNoteItemRequest> specialNoteItemListReader() {
    return createReader(SpecialNoteDispItemSyncResponse != null
        ? SpecialNoteDispItemSyncResponse.getSdOrderSpnItemList()
        : null, "specialNoteItem");
  }

  @Bean
  @StepScope
  public ListItemReader<DisplayItemRequest> storeDispItemListReader() {
    return createReader(SpecialNoteDispItemSyncResponse != null
        ? SpecialNoteDispItemSyncResponse.getStoreDispItemList()
        : null, "storeDispItem");
  }

  private <T> ItemWriter<T> createWriter(Consumer<List<T>> processor, String writerName) {
    return items -> {
      try {
        List<T> itemList = (List<T>) items.getItems();
        processor.accept(itemList);
        log.info("{}Writer: {} items 처리 완료", writerName, items.size());
      } catch (Exception e) {
        log.error("{}Writer 오류: {}", writerName, e.getMessage());
        throw e;
      }
    };
  }
}
