import os
from pathlib import Path

import click

# import find_files, gzip_file, gunzip_file
from easy_dataset_share import canary, robots, tos, zipping


def normalize_dir_path(dir_path: str) -> str:
    """Normalize directory path to remove leading slash and ensure proper formatting."""
    # Convert to Path object and resolve to absolute path
    path = Path(dir_path).resolve()
    # Convert back to string and ensure no leading slash issues
    return str(path)


@click.group()
def cli() -> None:
    """Making responsible dataset sharing easy!"""
    pass


@cli.command()
@click.argument("dir", type=click.Path(exists=True, file_okay=False, dir_okay=True))
@click.option("--password", "-p", default=None, help="Password for protection (default: no encryption)")
@click.option("--output", "-o", help="Output file path (optional)")
@click.option("--allow-crawling", "-a", is_flag=True, help="Allow crawling (default is to disallow all)")
@click.option("--user-agent", "-u", default="*", help="User-agent to target (default: *)")
@click.option("--num-canary-files", "-c", default=1, help="Number of canary files to create")
@click.option(
    "--embed-canaries",
    "-e",
    default=False,
    is_flag=True,
    help="Embed canaries in existing files (default is to create canary files)",
)
def magic_protect_dir(
    dir: str,
    password: str | None,
    output: str | None,
    allow_crawling: bool,
    user_agent: str,
    num_canary_files: int,
    embed_canaries: bool,
) -> None:
    """Zip a directory and password protect it in one step."""
    # try:
    # Normalize directory path
    dir = normalize_dir_path(dir)

    # Generate robots.txt in the directory
    robots_path = os.path.join(dir, "robots.txt")
    content = robots.generate_robots_txt(disallow_all=not allow_crawling, user_agent=user_agent)  # TODO: keep?
    robots.save_robots_txt(robots_path)
    click.echo(f"✅ Added robots.txt to {dir}")

    # Add canary files to the directory
    canary_string, canary_files = canary.create_canary_files_from_dataset(dir, "*", num_canary_files)
    click.echo(f"✅ Added {len(canary_files)} canary files to {dir}")
    if embed_canaries:
        # add canaries to existing files
        canary.insert_canaries_into_files(dir, canary_string)

    result = zipping.zip_and_password_protect(dir, password, output)
    click.echo(f"✅ Successfully protected {dir} -> {result}")
    # except Exception as e:
    #    click.echo(f"❌ Error protecting directory: {e}", err=True)


@cli.command()
@click.argument("file", type=click.Path(exists=True, file_okay=True, dir_okay=False))
@click.option("--password", "-p", required=False, default=None, help="Password for decryption")
@click.option("--output-dir", "-o", help="Output directory (optional)")
@click.option("--remove-canaries", "-rc", is_flag=True, help="Remove canary files after extraction")
@click.option("--canary-pattern", "-cp", default="dataset_entry_*.jsonl", help="Pattern to match canary files")
def magic_unprotect_dir(
    file: str,
    password: str | None,
    output_dir: str | None,
    remove_canaries: bool,
    canary_pattern: str,
) -> None:
    """Decrypt and extract a protected directory in one step."""
    try:
        result = zipping.unzip_and_decrypt(file, password, output_dir)
        click.echo(f"✅ Successfully extracted {file} -> {result}")

        # Normalize the result path
        result = normalize_dir_path(result)

        # Remove canary files from the extracted directory if requested
        if remove_canaries:
            canary.remove_canary_files(root_dir=result, canary_pattern=canary_pattern)
            canary_string = canary.generate_canary_string_from_dataset(result)
            # NOTE - one failure mode is that the canary string is not the same as the one that was used to protect the
            # directory in this case, the canary files will not be removed - some checking here needs to be done
            canary.remove_canaries_from_files(result, canary_string)
            click.echo(f"✅ Removed canary files from {result}")
        else:
            click.echo(f"ℹ️  Canary files preserved in {result} (use --remove-canaries to clean them)")

    except Exception as e:
        click.echo(f"❌ Error extracting protected file: {e}", err=True)


# get canary string for dir
@cli.command()
@click.argument("dir_path", type=click.Path(exists=True, file_okay=False, dir_okay=True))
def get_canary_string(dir_path: str) -> None:
    """Get the canary string for a directory."""
    # Normalize directory path
    dir_path = normalize_dir_path(dir_path)
    canary_string = canary.generate_canary_string_from_dataset(dir_path)
    click.echo(f"✅ Canary string: {canary_string}")


@cli.command()
@click.argument("root", type=click.Path(exists=True, file_okay=True, dir_okay=True))
@click.option("--pattern", "-p", default="*", help="Pattern to match existing files")
@click.option("--num-canary-files", "-f", default=1, help="Number of canary files to create")
def add_canary(root: str, pattern: str, num_canary_files: int) -> None:
    """Add canary files to a dataset for LLM training detection."""
    try:
        # Normalize root directory path
        root = normalize_dir_path(root)

        # Create canary files
        canary_string, canary_files = canary.create_canary_files_from_dataset(root, pattern, num_canary_files)
        click.echo(f"✅ Created {len(canary_files)} canary files")

    except Exception as e:
        click.echo(f"❌ Error adding canary files: {e}", err=True)


@cli.command()
@click.argument("root", type=click.Path(exists=True, file_okay=False, dir_okay=True))
@click.option("--canary-pattern", "-cp", default="dataset_entry_*.jsonl", help="Pattern to match canary files")
def remove_canary(root: str, canary_pattern: str) -> None:
    """Remove canary files from a dataset."""
    try:
        # Normalize root directory path
        root = normalize_dir_path(root)

        canary.remove_canary_files(root_dir=root, canary_pattern=canary_pattern)
        # canary.clean_dataset_of_canaries(root, pattern, remove_embedded, keep_metadata)

    except Exception as e:
        click.echo(f"❌ Error removing canary files: {e}", err=True)


@cli.command()
@click.argument("path", type=click.Path(exists=True, file_okay=True, dir_okay=True))
@click.option("--allow-crawling", "-a", is_flag=True, help="Allow crawling (default is to disallow all)")
@click.option("--user-agent", "-u", default="*", help="User-agent to target (default: *)")
def add_robots(path: str, allow_crawling: bool, user_agent: str) -> None:
    """Generate and save a robots.txt file to prevent LLM training."""
    try:
        # Generate robots.txt content
        content = robots.generate_robots_txt(disallow_all=not allow_crawling, user_agent=user_agent)

        # Save the file
        robots.save_robots_txt(path)

        click.echo(f"✅ Created robots.txt at: {path}")
        click.echo(f"🤖 User-agent: {user_agent}")

        if not allow_crawling:
            click.echo("🚫 Disallowing all crawling (prevents LLM training)")
            click.echo("💡 This helps prevent web crawlers from collecting your dataset for training")
        else:
            click.echo("✅ Allowing crawling")

        click.echo("\n📄 robots.txt content:")
        click.echo("---")
        click.echo(content)
        click.echo("---")

    except Exception as e:
        click.echo(f"❌ Error creating robots.txt: {e}", err=True)


@cli.command()
@click.argument("directory", type=click.Path(exists=True, file_okay=False, dir_okay=True))
@click.option("--company-name", "-c", default="Example Corp", help="Name of the company")
@click.option("--service-name", "-s", default="Example Service", help="Name of the service")
@click.option("--contact-email", "-e", default="support@example.com", help="Contact email address")
@click.option("--effective-date", "-d", help="Effective date (YYYY-MM-DD format, default: today)")
def add_tos(
    directory: str,
    company_name: str,
    service_name: str,
    contact_email: str,
    effective_date: str | None,
) -> None:
    """Generate and save a terms of service (tos.txt) file in the specified directory."""
    try:
        # Normalize directory path
        directory = normalize_dir_path(directory)

        # Generate tos.txt content
        content = tos.generate_tos_txt(
            company_name=company_name,
            service_name=service_name,
            contact_email=contact_email,
            effective_date=effective_date,
        )

        # Save the file in the directory
        tos_path = os.path.join(directory, "tos.txt")
        tos.save_tos_txt(tos_path)

        click.echo(f"✅ Created tos.txt in {directory}")
        click.echo(f"🏢 Company: {company_name}")
        click.echo(f"🔧 Service: {service_name}")
        click.echo(f"📧 Contact: {contact_email}")

        if effective_date:
            click.echo(f"📅 Effective Date: {effective_date}")
        else:
            click.echo("📅 Effective Date: Today")

        click.echo("\n📄 tos.txt content:")
        click.echo("---")
        click.echo(content)
        click.echo("---")

    except Exception as e:
        click.echo(f"❌ Error creating tos.txt: {e}", err=True)


if __name__ == "__main__":
    cli()
