from os import listdir
from os.path import isdir, join
from importlib import metadata

import click

from vernissage.functions import parse_aspect_ratio, process_image
from vernissage.messages import HELP_MESSAGES, ERROR_MESSAGES


@click.group()
def cli():
    pass


@click.command()
def version():
    """Display the current version of vernissage."""
    try:
        version = metadata.version("vernissage")
        click.echo(f"vernissage version {version}")
    except metadata.PackageNotFoundError:
        click.echo("vernissage version unknown (package not installed)")


@click.command()
@click.argument("input", type=click.Path(exists=True))
@click.argument("output", type=click.Path())
@click.option("--output-format", "-f", default=None, help=HELP_MESSAGES["output_format"])
@click.option("--max-size", "-s", default="936", help=HELP_MESSAGES["max_size"])
@click.option("--border-size", "-b", default="72", help=HELP_MESSAGES["border_size"])
@click.option("--border-color", "-c", default="250,250,250", help=HELP_MESSAGES["border_color"])
@click.option("--aspect-ratio", "-a", default=None, help=HELP_MESSAGES["aspect_ratio"])
def process(
    input: str,
    output: str,
    max_size: str,
    border_size: str,
    border_color: str,
    output_format: str | None,
    aspect_ratio: str | None
) -> None:
    """Process a single image by adding borders and resizing."""
    # Parse color tuple
    try:
        color_tuple = tuple(int(x.strip()) for x in border_color.split(","))
        if len(color_tuple) != 3:
            raise ValueError("Color must have exactly 3 components (R,G,B)")
    except ValueError as e:
        raise click.BadParameter(ERROR_MESSAGES["invalid_color_format"])
    
    # Parse aspect ratio if provided
    try:
        parsed_aspect_ratio = parse_aspect_ratio(aspect_ratio)
    except ValueError as e:
        raise click.BadParameter(ERROR_MESSAGES["invalid_aspect_ratio"])
    
    process_image(
        input_path=input, 
        output_path=output, 
        output_format=output_format,
        max_size=int(max_size),
        border_size=int(border_size),
        border_color=color_tuple,
        aspect_ratio=parsed_aspect_ratio
    )


@click.command()
@click.argument("input", type=click.Path(exists=True, file_okay=False))
@click.argument("output", type=click.Path(file_okay=False))
@click.option("--output-format", "-f", default="jpeg", help=HELP_MESSAGES["batch_output_format"])
@click.option("--max-size", "-s", default="936", help=HELP_MESSAGES["max_size"])
@click.option("--border-size", "-b", default="72", help=HELP_MESSAGES["border_size"])
@click.option("--border-color", "-c", default="250,250,250", help=HELP_MESSAGES["border_color"])
@click.option("--aspect-ratio", "-a", default=None, help=HELP_MESSAGES["aspect_ratio"])
def batch(
    input: str,
    output: str,
    output_format: str,
    max_size: str,
    border_size: str,
    border_color: str,
    aspect_ratio: str | None
) -> None:
    """Process multiple images in batch mode by adding borders and resizing."""
    # Parse color tuple
    try:
        color_tuple = tuple(int(x.strip()) for x in border_color.split(","))
        if len(color_tuple) != 3:
            raise ValueError("Color must have exactly 3 components (R,G,B)")
    except ValueError as e:
        raise click.BadParameter(ERROR_MESSAGES["invalid_color_format"])
    from os import makedirs
    from os.path import exists
    
    # Create output directory if it doesn't exist
    if not exists(output):
        makedirs(output)
        click.echo(f"Created output directory: {output}")
    
    # Parse aspect ratio if provided
    parsed_aspect_ratio = None
    if aspect_ratio:
        try:
            parts = aspect_ratio.split(":")
            if len(parts) == 2:
                parsed_aspect_ratio = (float(parts[0]), float(parts[1]))
            else:
                raise click.BadParameter(ERROR_MESSAGES["invalid_aspect_ratio"])
        except ValueError:
            raise click.BadParameter(ERROR_MESSAGES["invalid_aspect_ratio"])
    
    if isdir(input):
        files = [join(input, file) for file in listdir(input)]
        for index, file in enumerate(files):
            try:
                click.echo(f"Processing: {file}")
                process_image(
                    input_path=file,
                    output_path=join(output, f"{index}.{output_format.lower()}"),
                    output_format=output_format,
                    max_size=int(max_size),
                    border_size=int(border_size),
                    border_color=color_tuple,
                    aspect_ratio=parsed_aspect_ratio
                )
            except IsADirectoryError:
                click.echo(f"Skipping directory: {file}")
            except Exception as e:
                click.echo(f"Error processing {file}: {str(e)}")
    else:
        click.echo(ERROR_MESSAGES["not_a_directory"].format(input=input), err=True)


cli.add_command(process)
cli.add_command(batch)
cli.add_command(version)
