package com.kospo.talk.service.impl;

import com.kospo.talk.config.utils.CommonUtils;
import com.kospo.talk.model.*;
import com.kospo.talk.payload.*;
import com.kospo.talk.repository.*;
import com.kospo.talk.service.WorkService;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class WorkServiceImpl implements WorkService {
    private final TalkRepository talkRepository;
    private final WorkRepository workRepository;
    private final WorkSRepository workSRepository;
    private final WorkLogoRepository workLogoRepository;
    private final ManualRepository manualRepository;
    private final SmUserRepository smUserRepository;
    private final UserRepository userRepository;
    @Value("${server.logo}")
    private String logoAttach;

    @Override
    @Transactional
    public WorkDto findByWorkId(String workId) {
        return WorkDto.to(workRepository.findByWorkId(workId));
    }

    @Override
    public List<WorkCategoryDto> findByWorkDepth(String pWorkId) {
        return workRepository.findByWorkDepth(pWorkId).stream().map(WorkCategoryDto::to).collect(Collectors.toList());
    }

    @Override
    public List<WorkCategoryDto> findByWorkSearech(String name) {
        return workRepository.findByWorkSearch(name).stream().map(WorkCategoryDto::to).collect(Collectors.toList());
    }

    @Override
    public List<WorkTreeDto> findAll() {
        return workRepository.findAll().stream().map(WorkTreeDto::to).toList();
    }

    @Override
    public List<WorkDto> findSabun(String sabun) {
        return workRepository.findBySabun(sabun).stream().map(WorkDto::to).toList();
    }

    @Override
    public Work findByTalkId(String talkId) {
        return workRepository.findByTalkId(talkId);
    }

    @Override
    public List<WorkDepthDto> findByAlLDepth(String workId) {
        return workRepository.findByAlLDepth(workId).stream().map(WorkDepthDto::to).toList();
    }

    @Override
    @Transactional
    public WorkDto findByWorkUrl(String url, String workId, String sabun) {
        WorkDto workDto = null;
        if(url.equals("")) {
            workDto = WorkDto.to(workRepository.findByWorkId(workId));
        } else {
            WorkS workS = workSRepository.findByWorkUrlLike("%" + url + "%");
            workDto = WorkDto.to(workRepository.findByWorkId(workS.getWorkId()));
        }
        List<User> smUsers = userRepository.findOnlineSM(workDto.getWorkId());
        if(smUsers.isEmpty()) {
            workDto.setOnlineYn(false);
        } else {
            workDto.setOnlineYn(true);
        }


        long notStart = talkRepository.countByWorkIdAndStartYn(workDto.getWorkId(), false);
        long smUserCnt = smUserRepository.countByIdWorkId(workDto.getWorkId());
        if(smUserCnt == 0) smUserCnt = 1;
        int avgNotStart = (int) (notStart / smUserCnt);
        workDto.setNotStart(avgNotStart);
        return workDto;
    }

    @Override
    public WorkLogoDto logoSave(WorkLogoDto workLogoDto) {
        Optional<WorkLogo> fWorkLogo  = workLogoRepository.findById(workLogoDto.getWorkId());
        WorkLogo workLogo = null;
        if(!fWorkLogo.isEmpty()) {
            workLogo = fWorkLogo.get();
            workLogo.setOnm(workLogoDto.getOnm());
            workLogo.setVnm(logoUpload(workLogoDto.getData()));
            workLogo.setPath(logoAttach);
            workLogoRepository.save(workLogo);
        } else {
            workLogo = WorkLogo.builder()
                .workId(workLogoDto.getWorkId())
                    .size((long) workLogoDto.getData().length)
                    .onm(workLogoDto.getOnm())
                    .path(logoAttach)
                    .type(workLogoDto.getType())
                    .vnm(logoUpload(workLogoDto.getData()))
                    .insDate(LocalDateTime.now())
                    .build();
            workLogoRepository.save(workLogo);
        }

        return WorkLogoDto.to(workLogo);
    }

    private String logoUpload(byte[] binary) {
        String vnm = CommonUtils.generateFileName();
        try {
            try (FileOutputStream fos = new FileOutputStream(new File(logoAttach, vnm))) {
                fos.write(binary);
            }
        } catch(IOException e) {
            throw new RuntimeException(e);
        }
        return vnm;
    }


}
