package service

import (
	"bytes"
	"crypto/md5"
	"crypto/tls"
	"fmt"
	"image"
	"image/jpeg"
	"image/png"
	"net/http"
	"os"
	"path/filepath"
	"time"

	"golang.org/x/image/draw"
)

const CacheDir = "cache/images"

type ImageService struct {
	client *http.Client
}

func NewImageService() *ImageService {
	os.MkdirAll(CacheDir, 0755)

	// Use custom transport to skip SSL verification
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}

	return &ImageService{
		client: &http.Client{
			Transport: tr,
			Timeout:   15 * time.Second,
		},
	}
}

func (s *ImageService) GetProxiedImage(url string, width int) ([]byte, string, error) {
	hash := md5.Sum([]byte(fmt.Sprintf("%s_%d", url, width)))
	cacheKey := fmt.Sprintf("%x.jpg", hash)
	cachePath := filepath.Join(CacheDir, cacheKey)

	// Check cache
	if _, err := os.Stat(cachePath); err == nil {
		data, err := os.ReadFile(cachePath)
		if err == nil {
			return data, "image/jpeg", nil
		}
	}

	// Fetch with custom request to set headers
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, "", err
	}
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
	req.Header.Set("Referer", "https://ophim1.com/")

	resp, err := s.client.Do(req)
	if err != nil {
		return nil, "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return nil, "", fmt.Errorf("image fetch failed: %d", resp.StatusCode)
	}

	// Decode
	var img image.Image
	contentType := resp.Header.Get("Content-Type")

	switch contentType {
	case "image/jpeg":
		img, err = jpeg.Decode(resp.Body)
	case "image/png":
		img, err = png.Decode(resp.Body)
	default:
		// Attempt agnostic decode
		img, _, err = image.Decode(resp.Body)
	}

	if err != nil {
		return nil, "", fmt.Errorf("decode error: %v", err)
	}

	// Resize if needed
	if width > 0 && img.Bounds().Dx() > width {
		bounds := img.Bounds()
		ratio := float64(width) / float64(bounds.Dx())
		height := int(float64(bounds.Dy()) * ratio)

		dst := image.NewRGBA(image.Rect(0, 0, width, height))
		draw.CatmullRom.Scale(dst, dst.Bounds(), img, bounds, draw.Over, nil)
		img = dst
	}

	// Encode to JPEG
	var buf bytes.Buffer
	if err := jpeg.Encode(&buf, img, &jpeg.Options{Quality: 80}); err != nil {
		return nil, "", fmt.Errorf("jpeg encode error: %v", err)
	}

	jpegData := buf.Bytes()

	// Write cache
	os.WriteFile(cachePath, jpegData, 0644)

	return jpegData, "image/jpeg", nil
}
