import os
from pathlib import Path

from fastapi import HTTPException
from fastapi.responses import FileResponse
from fastapi import APIRouter, Request, FastAPI
from PIL import Image


class FileHandler:

	def __init__(self, category=None, image_type=None, filename=None) -> Path:
		self.filename = filename
		self.category = category
		self.image_type = image_type

	@property
	def src_file(self) -> str:
		src_path = "data/{category}/images/{filename}"
		return src_path.format( category = self.category, filename = self.filename )

	@property
	def dest_file(self) -> str:
		base_url = "/images/{category}/{filename}"
		return base_url.format( category = self.category, filename = self.filename )

	@property
	def dest_filename(self) -> str:
		base_url = "static/images/{category}/{image_type}/{filename}"
		return base_url.format( category = self.category, image_type = self.image_type, filename = self.filename )
	@property
	def dest_filename_webp(self) -> str:
		base_url = "static/images/{category}/{image_type}/{filename}"
		path = Path( base_url.format( category = self.category, image_type = self.image_type, filename = self.filename ) )
		if path.suffix != ".webp":
			path = path.with_suffix( ".webp" )
		return str(path)

	@property
	def dest_path(self) -> str:
		base_url = "static/images/{category}/{image_type}"
		return base_url.format( category = self.category, image_type = self.image_type )

	def __str__(self):
		return (
			f"FileHandler(\n"
			f"  filename='{self.filename}',\n"
			f"  category='{self.category}',\n"
			f"  image_type='{self.image_type}',\n"
			f"  src_file='{self.src_file}',\n"
			f"  dest_file='{self.dest_file}',\n"
			f"  dest_filename='{self.dest_filename}',\n"
			f"  dest_path='{self.dest_path}'\n"
			f")"
		)

	def get_category(self, file_path):
		# List all categories in the data directory
		categories = [
			name for name in os.listdir( "data/" )
			if os.path.isdir( os.path.join( "data/", name ) )
		]

		# Search for the category in the file path
		for category in categories:
			if f"/{category}/" in file_path or f"\\{category}\\" in file_path:
				return category

		# Return None if no category matches
		return None


class ImageService:

	def __init__(self,app: FastAPI):
		self.router = APIRouter()
		self.app = app
		self.IMAGE_SIZES = self.app.state.IMAGE_SIZES
		#self._ensure_directories_exist()
		self._add_routes()




	def __str__(self):
		"""
		Provides a string representation of the class instance.
		"""
		base_paths_str = "\n".join(
			[f"{key}: {value}" for key, value in self.base_paths.items()]
		)
		image_sizes_str = "\n".join(
			[
				f"{key}: width={value['width']}, height={value['height']}"
				for key, value in self.image_sizes.items()
			]
		)
		return f"<Class:ImageService Base Paths:{base_paths_str} Image Sizes:\n{image_sizes_str}"

	def get_image_size(self, image_type: str) -> dict:
		"""
		Retrieve the width and height for a given image type from the app state.

		Args:
			request (Request): FastAPI request object.
			image_type (str): The type of the image (e.g., 'thumbnails').

		Returns:
			dict: A dictionary with 'width' and 'height'.
		"""

		image_sizes = self.app.state.IMAGE_SIZES
		if image_type not in image_sizes:
			raise ValueError( f"Invalid image type: {image_type}. Must be one of {list( image_sizes.keys() )}" )

		return image_sizes[image_type]

	def _add_routes(self):
		self.router.add_api_route(
			"/image/{category}/{type}/{filename}",
			self.get_image,
			methods=["GET"],
			response_class=FileResponse,
		)

	async def get_image(self, category: str, type: str, filename: str):
		"""
		Retrieve an image file from the specified category and type.
		"""
		file_path = self._resolve_path(category, type, filename)
		return FileResponse(file_path)

	def validate_image(self, file_path:FileHandler=None, width:int=None, height:int=None, overwrite = True ) -> bool:
		if not os.path.exists( file_path.dest_filename ):
			with Image.open( file_path.src_file ) as img:
				print(file_path.src_file)
				self._resize_image( img, file_path, width, height )
			return True

		with Image.open( file_path.dest_filename ) as img:
			if img.width != width or img.height != height:
				if overwrite:
					self._resize_image( img, file_path, width, height )
				return False
		return True

	def _resize_image(self, img: Image.Image, file_path: FileHandler, width: int, height: int):
		resized_img = img.resize( (width, height), Image.Resampling.LANCZOS )
		os.makedirs(file_path.dest_path,exist_ok = True)
		resized_img.save( file_path.dest_filename )
		resized_img.save( file_path.dest_filename_webp, format = "WEBP", quality = 90 )  # Adjust quality as needed
		print(file_path.dest_filename_webp)

	async def get_image(self, category: str, type: str, filename: str):
		file_path = self._resolve_path( category, type, filename )
		return FileResponse( file_path )

	def image_tag(self, category: str, image_type: str, filename: str, alt: str = "", width: int = None,
	               height: int = None,css_class:str=None) -> str:
		"""
		Generate an HTML <img> tag with default sizes if dimensions are not provided.
		"""
		# Use default sizes if none are provided
		default_size = self.get_image_size( image_type)
		width = width or default_size.get( "width" )
		height = height or default_size.get( "height" )
		file_path = FileHandler(category = category,image_type = image_type,filename = filename)
		p = Path(file_path.dest_path)
		p.mkdir(parents = True, exist_ok = True)
		self.validate_image( file_path, width = width,height=height, overwrite = True )
		tag = f'<img src="/{file_path.dest_filename_webp}" alt="{alt}"'
		# if width:
		# 	tag += f' width="{width}"'
		# if height:
		# 	tag += f' height="{height}"'
		if css_class:
			tag += f' class="{css_class}"'
		tag += ">"

		return tag