from PIL import Image, ImageFont, ImageDraw
import requests
import numpy as np
import cv2
import os
from datetime import datetime
import logging

class PostImageManager:
    def __init__(self, logger, font_path):
        self.logger = logger
        self.font_path = font_path

        # 폰트 로드
        self.font_load()


    def font_load(self):
        # 폰트 로드
        try:
            self.font = ImageFont.truetype(self.font_path, 36)
            self.logger.log(f"폰트 로드 성공: {self.font_path}", level=logging.DEBUG)
        except Exception as e:
            self.logger.log(f"커스텀 폰트 로드 실패 ({self.font_path}): {e}", level=logging.WARNING)
            try:
                # 기본 폰트 사용
                self.font = ImageFont.load_default()
                self.logger.log("기본 폰트를 사용합니다.", level=logging.INFO)
            except Exception as e2:
                self.logger.log(f"기본 폰트 로드도 실패: {e2}", level=logging.ERROR)
                # 최후의 수단으로 None 설정
                self.font = None

    def save_image_to_path(self, image, path):
        try:
            if image:
                # 이미지를 저장 경로에 저장
                self.logger.log(f"이미지 저장 완료 : {path}", level=logging.INFO)
                image.save(path, format='PNG')
                return path
            
        except Exception as e:
            raise RuntimeError(f"이미지 저장 중 오류 발생: {e}")

    def add_watermark(self, image_data, watermark_text="Watermark", opacity_percent=30, angle=30, font_size=36):
        """
        이미지에 텍스트 워터마크를 이미지 전체에 걸쳐서 추가하는 함수
        :param image_data: PIL 이미지 객체
        :param watermark_text: 워터마크로 추가할 텍스트
        :param opacity_percent: 워터마크의 투명도 (0~100)
        :param angle: 워터마크 텍스트 회전 각도 (기본 30도)
        :param font_size: 워터마크 텍스트의 폰트 크기 (기본 36)
        :return: 워터마크가 추가된 이미지
        """
        try:
            if isinstance(image_data, np.ndarray):
                image_data = Image.fromarray(cv2.cvtColor(image_data, cv2.COLOR_BGR2RGB))
        
            # 폰트가 로드되지 않은 경우 원본 이미지 반환
            if self.font is None:
                self.logger.log("폰트가 로드되지 않아 워터마크를 추가할 수 없습니다. 원본 이미지를 반환합니다.", level=logging.WARNING)
                return image_data
                
            # 이미지 복사본 생성
            watermark_image = image_data.copy()
            
            # 폰트 설정 (안전한 폰트 로딩)
            try:
                # self.font가 있으면 크기만 조정해서 새 폰트 생성
                if hasattr(self, 'font_path') and os.path.exists(self.font_path):
                    font = ImageFont.truetype(self.font_path, font_size)
                else:
                    # 크기를 조정할 수 없으면 기존 폰트 사용
                    font = self.font
            except Exception as e:
                self.logger.log(f"폰트 크기 조정 실패: {e}. 기본 폰트를 사용합니다.", level=logging.WARNING)
                font = self.font

            # 텍스트 투명도를 0~255로 변환
            opacity = int(255 * (opacity_percent / 100))

            # 텍스트 크기 측정 (textbbox 사용)
            draw = ImageDraw.Draw(watermark_image)
            bbox = draw.textbbox((0, 0), watermark_text, font=font)
            text_width, text_height = bbox[2] - bbox[0], bbox[3] - bbox[1]

            # 이미지 크기
            width, height = image_data.size

            # 워터마크 레이어 생성
            watermark_layer = Image.new("RGBA", (width, height))  # RGBA 이미지 생성

            # 지그재그 간격 설정
            zigzag_step = int(text_height * 2)  # Y축의 지그재그 간격


            # 이미지 전체에 반복적으로 워터마크 텍스트 그리기 (지그재그 형태)
            for y in range(0, height, zigzag_step):
                for x in range(0, width, int(text_width * 3)):  # 3배 너비 간격으로 반복
                    # 텍스트가 한 줄씩 지그재그 형태로 X축을 교차하여 이동
                    x_offset = (y // zigzag_step) % 2 * int(text_width * 1.5)  # 짝수 행에서는 X축을 약간 이동

                    # 텍스트 레이어 생성
                    text_layer = Image.new("RGBA", (text_width, text_height), (255, 255, 255, 0))
                    text_draw = ImageDraw.Draw(text_layer)
                    
                    # 텍스트 그리기
                    text_draw.text((0, 0), watermark_text, fill=(255, 255, 255, opacity), font=font)
                    
                    # 텍스트 회전
                    rotated_text_layer = text_layer.rotate(angle, expand=1)
                    
                    # 회전된 텍스트를 워터마크 레이어에 추가
                    watermark_layer.paste(rotated_text_layer, (x + x_offset, y), rotated_text_layer)

            # 원본 이미지와 워터마크 레이어 합성
            watermark_image = Image.alpha_composite(watermark_image.convert("RGBA"), watermark_layer)
            
            # 최종적으로 RGB 형식으로 변환 후 반환
            return watermark_image.convert("RGB")
        
        except Exception as e:
            self.logger.log(f"워터마크 추가 중 오류 발생: {e}", level=logging.ERROR, exc_info=True)
            return image_data

    def crop_image(self, image, is_thumb=False, crop_percentage=0.01):
        """이미지를 주어진 퍼센트만큼 크롭하는 함수"""
        if is_thumb:
            crop_percentage = 0.03
            self.logger.log(f"썸네일 이미지 이므로 크롭 3%로 조정", level=logging.DEBUG)

        width, height = image.size
        left = width * crop_percentage
        top = height * crop_percentage
        right = width * (1 - crop_percentage)
        bottom = height * (1 - crop_percentage)

        cropped_image = image.crop((left, top, right, bottom))

        if self.debug:
            # 디버그 모드일 경우 크롭 전후 다양한 비율로 이미지 저장
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            original_image_path = os.path.join(os.getcwd(), f"original_image_{timestamp}.png")
            image.save(original_image_path)  # 크롭 전 이미지 저장
            self.logger.log(f"크롭 전 이미지 저장됨: {original_image_path}", level=logging.DEBUG)

            # 1%, 2%, 3% 크롭 이미지 저장
            crop_alternatives = [0.01, 0.02, 0.03]
            for crop in crop_alternatives:
                left_alt = width * crop
                top_alt = height * crop
                right_alt = width * (1 - crop)
                bottom_alt = height * (1 - crop)

                cropped_alt_image = image.crop((left_alt, top_alt, right_alt, bottom_alt))
                cropped_image_path = os.path.join(os.getcwd(), f"cropped_image_{int(crop*100)}_{timestamp}.png")
                cropped_alt_image.save(cropped_image_path)
                self.logger.log(f"{int(crop*100)}% 크롭된 이미지 저장됨: {cropped_image_path}", level=logging.DEBUG)

        return cropped_image