package com.kospo.talk.service.impl;

import com.kospo.talk.config.utils.CommonUtils;
import com.kospo.talk.model.TalkAttach;
import com.kospo.talk.model.TalkAttachId;
import com.kospo.talk.repository.TalkAttachRepository;
import com.kospo.talk.service.TalkAttachService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
@RequiredArgsConstructor
public class TalkAttachServiceImpl implements TalkAttachService {
    private final TalkAttachRepository talkAttachRepository;

    @Override
    public List<TalkAttach> findByTalkId(String talkId) {
        return talkAttachRepository.findByIdTalkId(talkId);
    }

    @Override
    public void saveAll(List<TalkAttach> talkAttachList) {
        talkAttachRepository.saveAll(talkAttachList);
    }

    @Override
    public void save(TalkAttach talkAttach) {
        talkAttachRepository.save(talkAttach);
    }

    @Override
    public byte[] readFile(TalkAttachId id) {
        TalkAttach att = talkAttachRepository.findById(id).get();
        File inputFile = new File(att.getPath(), att.getVnm());
        BufferedImage originalImage = null;
        FileInputStream fis = null;

        try {
            fis = new FileInputStream(inputFile);

            return fis.readAllBytes();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public byte[] readThumb(TalkAttachId id, int size) {
        TalkAttach att = talkAttachRepository.findById(id).get();
        File inputFile = new File(att.getPath(), att.getVnm());
        BufferedImage originalImage = null;
        ByteArrayOutputStream baos = null;

        try {
            originalImage = ImageIO.read(inputFile);

            // 원본 이미지의 비율을 유지하면서 썸네일 크기 계산
            double widthRatio = (double) size / originalImage.getWidth();
            double heightRatio = (double) size / originalImage.getHeight();
            double ratio = Math.max(widthRatio, heightRatio);

            int newWidth = (int) (originalImage.getWidth() * ratio);
            int newHeight = (int) (originalImage.getHeight() * ratio);

            // 새 이미지 생성
            BufferedImage thumbnailImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);

            // 이미지 크기 조정
            Graphics2D g2d = thumbnailImage.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
            g2d.drawImage(originalImage, 0, 0, newWidth, newHeight, null);
            g2d.dispose();

            thumbnailImage.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);

            // 썸네일을 바이트 배열로 변환
            baos = new ByteArrayOutputStream();
            ImageIO.write(thumbnailImage, "png", baos);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return baos.toByteArray();
    }

    @Override
    public List<TalkAttach> getTalkAttachList(String talkId, String sabun, String insDate) {
        return talkAttachRepository.findByList(talkId, sabun, CommonUtils.stringToDate(insDate, "yyyy-MM-dd HH:mm:ss.SSSSSS"));
    }

    @Override
    public List<TalkAttach> getTalkAttachList(String talkId, String sabun, LocalDateTime insDate) {
        return talkAttachRepository.findByList(talkId, sabun, insDate);
    }

    @Override
    public ByteArrayInputStream getTalkAttachCompression(List<TalkAttach> attaches) {

        ByteArrayOutputStream baos = null;
        ZipOutputStream zos = null;

        FileInputStream fis = null;

        try {
            baos = new ByteArrayOutputStream();
            zos = new ZipOutputStream(baos);
            for (TalkAttach attach : attaches) {
                ZipEntry entry = new ZipEntry(attach.getOnm());

                zos.putNextEntry(entry);

                File inputFile = new File(attach.getPath(), attach.getVnm());

                fis = new FileInputStream(inputFile);

                byte[] buffer = new byte[1024];
                int length;
                while((length = fis.read(buffer)) > 0) {
                    zos.write(buffer, 0, length);
                }

                zos.closeEntry();
            }

            zos.close();
            return new ByteArrayInputStream(baos.toByteArray());


        } catch(IOException e) {
            throw new RuntimeException(e);
        } finally {
            if(fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if(zos != null) {
                try {
                    zos.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if(baos != null) {
                try {
                    baos.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    @Override
    public ByteArrayInputStream getTalkAttachByte(TalkAttach attach) {


        FileInputStream fis = null;
        ByteArrayInputStream bais = null;
        File inputFile = new File(attach.getPath(), attach.getVnm());

        try {
            fis = new FileInputStream(inputFile);
            bais = new ByteArrayInputStream(fis.readAllBytes());

            return bais;
        } catch(IOException e) {
            throw new RuntimeException(e);
        } finally {
            if(fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if(bais != null) {
                try {
                    bais.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}
