package com.kamco.cd.training.schedule.service;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.kamco.cd.training.postgres.core.ModelTrainMetricsJobCoreService;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor
public class ModelTestMetricsJobService {

  private final ModelTrainMetricsJobCoreService modelTrainMetricsJobCoreService;

  @Value("${spring.profiles.active}")
  private String profile;

  /**
   * 실행중인 profile
   *
   * @return
   */
  private boolean isLocalProfile() {
    return "local".equalsIgnoreCase(profile);
  }

  //  @Scheduled(cron = "0 * * * * *")
  public void findTestValidMetricCsvFiles() {
    //    if (isLocalProfile()) {
    //      return;
    //    }

    List<Long> modelIds =
        modelTrainMetricsJobCoreService
            .getTrainMetricSaveNotYetModelIds(); // TODO: uid, uuid ? 가져오기로 해야함

    if (modelIds.isEmpty()) {
      return;
    }

    Session session = null;
    ChannelSftp sftp = null;

    JSch jsch = new JSch();

    //    try {
    //      session = jsch.getSession("kcomu", "192.168.2.86", 22);
    //      session.setPassword("Kamco2025!");
    //
    //      Properties config = new Properties();
    //      config.put("StrictHostKeyChecking", "no");
    //      session.setConfig(config);
    //
    //      session.connect();
    //
    //      sftp = (ChannelSftp) session.openChannel("sftp");
    //      sftp.connect();

    //      InputStream csvInputStream =
    // sftp.get("/home/kcomu/data/response/test/metrics/train.csv");

    String localPath = "C:\\data\\upload\\train.csv";
    try (BufferedReader reader =
        Files.newBufferedReader(Paths.get(localPath), StandardCharsets.UTF_8); ) {

      log.info("### localPath={}", localPath);
      CSVParser parser = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(reader);

      List<Object[]> batchArgs = new ArrayList<>();

      for (CSVRecord record : parser) {

        int epoch = Integer.parseInt(record.get("Epoch"));
        long iteration = Long.parseLong(record.get("Iteration"));
        double Loss = Double.parseDouble(record.get("Loss"));
        double LR = Double.parseDouble(record.get("LR"));
        float time = Float.parseFloat(record.get("Time"));

        batchArgs.add(new Object[] {modelIds.getFirst(), epoch, iteration, Loss, LR, time});
      }

      modelTrainMetricsJobCoreService.insertModelMetricsTrain(batchArgs);

    } catch (IOException e) {
      throw new RuntimeException(e);
    }

    String validationPath = "C:\\data\\upload\\val.csv";
    try (BufferedReader reader =
        Files.newBufferedReader(Paths.get(validationPath), StandardCharsets.UTF_8); ) {

      log.info("### validationPath={}", validationPath);
      CSVParser parser = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(reader);

      List<Object[]> batchArgs = new ArrayList<>();

      for (CSVRecord record : parser) {

        int epoch = Integer.parseInt(record.get("Epoch"));
        float aAcc = Float.parseFloat(record.get("aAcc"));
        float mFscore = Float.parseFloat(record.get("mFscore"));
        float mPrecision = Float.parseFloat(record.get("mPrecision"));
        float mRecall = Float.parseFloat(record.get("mRecall"));
        float mIoU = Float.parseFloat(record.get("mIoU"));
        float mAcc = Float.parseFloat(record.get("mAcc"));
        float changed_fscore = Float.parseFloat(record.get("changed_fscore"));
        float changed_precision = Float.parseFloat(record.get("changed_precision"));
        float changed_recall = Float.parseFloat(record.get("changed_recall"));
        float unchanged_fscore = Float.parseFloat(record.get("unchanged_fscore"));
        float unchanged_precision = Float.parseFloat(record.get("unchanged_precision"));
        float unchanged_recall = Float.parseFloat(record.get("unchanged_recall"));

        batchArgs.add(
            new Object[] {
              modelIds.getFirst(),
              epoch,
              aAcc,
              mFscore,
              mPrecision,
              mRecall,
              mIoU,
              mAcc,
              changed_fscore,
              changed_precision,
              changed_recall,
              unchanged_fscore,
              unchanged_precision,
              unchanged_recall
            });
      }

      modelTrainMetricsJobCoreService.insertModelMetricsValidation(batchArgs);

    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    //    } catch (JSchException | SftpException e) {
    //      throw new RuntimeException(e);
    //    }
    modelTrainMetricsJobCoreService.updateModelMetricsTrainSaveYn(modelIds.getFirst(), "step1");
  }
}
