"""
CLI tool for Garmin health data synchronization.

Usage:
    python -m health.cli.sync status           # Show sync status
    python -m health.cli.sync sync-now         # Sync today
    python -m health.cli.sync sync --days 7    # Sync last 7 days
    python -m health.cli.sync backfill --start-date 2024-01-01  # Historical backfill
"""

import sys
from datetime import date, timedelta
from typing import Optional

import click

from health import config
from health.services.data_sync import HealthDataSync
from health.utils.date_utils import parse_date, get_yesterday
from health.utils.logging_config import setup_logger
from health.utils.exceptions import GarminAuthError, SyncError

logger = setup_logger(__name__)


@click.group()
def cli() -> None:
    """Garmin Health Data Sync CLI."""
    pass


@cli.command()
def status() -> None:
    """Show synchronization status for all data types."""
    click.echo("📊 Health Data Sync Status\n")

    sync_service = HealthDataSync()
    status_info = sync_service.get_sync_status()

    # Group by status
    synced = []
    never_synced = []

    for data_type, info in status_info.items():
        if info["status"] == "synced":
            synced.append((data_type, info))
        else:
            never_synced.append(data_type)

    # Display synced data types
    if synced:
        click.echo("✅ Synced Data Types:")
        for data_type, info in synced:
            description = config.DATA_TYPE_CONFIG.get(data_type, {}).get(
                "description", ""
            )
            click.echo(
                f"  • {data_type:20} Last sync: {info['last_sync_date']}  "
                f"({info['total_records']} records) - {description}"
            )

    # Display never synced
    if never_synced:
        click.echo("\n⚠️  Never Synced:")
        for data_type in never_synced:
            description = config.DATA_TYPE_CONFIG.get(data_type, {}).get(
                "description", ""
            )
            click.echo(f"  • {data_type:20} {description}")

    click.echo(f"\n📁 Data directory: {config.DATA_DIR}")
    click.echo(f"🗄️  Database: {config.DB_PATH}")


@cli.command()
@click.option(
    "--days",
    "-d",
    type=int,
    default=1,
    help="Number of days to sync (from yesterday backwards)",
)
@click.option("--force", "-f", is_flag=True, help="Force re-sync existing data")
def sync(days: int, force: bool) -> None:
    """Sync health data for recent days."""
    try:
        # Calculate date range
        end_date = get_yesterday()
        start_date = end_date - timedelta(days=days - 1)

        click.echo(f"🔄 Syncing health data from {start_date} to {end_date}")
        if force:
            click.echo("   (Force mode: re-syncing existing data)")

        # Initialize sync service
        sync_service = HealthDataSync()

        # Authenticate
        click.echo("🔐 Authenticating with Garmin Connect China...")
        sync_service.authenticate()
        click.echo("✅ Authentication successful\n")

        # Sync all metrics
        results = sync_service.sync_all_metrics(
            start_date, end_date, force=force
        )

        # Display results
        click.echo("\n📊 Sync Results:")
        total_synced = 0
        total_errors = 0

        for metric_type, stats in results.items():
            synced = stats.get("synced", 0)
            skipped = stats.get("skipped", 0)
            errors = stats.get("errors", 0)

            total_synced += synced
            total_errors += errors

            status_icon = "✓" if errors == 0 else "⚠"
            click.echo(
                f"  {status_icon} {metric_type:20} "
                f"Synced: {synced:3}, Skipped: {skipped:3}, Errors: {errors:3}"
            )

        click.echo(
            f"\n{'✅' if total_errors == 0 else '⚠️ '} "
            f"Total: {total_synced} records synced, {total_errors} errors"
        )

        sys.exit(0 if total_errors == 0 else 1)

    except GarminAuthError as e:
        click.echo(f"\n❌ Authentication failed: {e}", err=True)
        click.echo(
            "   Please check your Garmin credentials in the .env file.", err=True
        )
        sys.exit(1)
    except Exception as e:
        click.echo(f"\n❌ Sync failed: {e}", err=True)
        logger.exception("Sync failed")
        sys.exit(1)


@cli.command()
@click.option(
    "--start-date",
    "-s",
    required=True,
    help="Start date for backfill (YYYY-MM-DD)",
)
@click.option(
    "--end-date",
    "-e",
    default=None,
    help="End date for backfill (defaults to yesterday)",
)
@click.option(
    "--batch-size",
    "-b",
    type=int,
    default=config.DEFAULT_BATCH_SIZE_DAYS,
    help=f"Days per batch (default: {config.DEFAULT_BATCH_SIZE_DAYS})",
)
@click.option(
    "--metrics",
    "-m",
    multiple=True,
    help="Specific metrics to sync (can be specified multiple times)",
)
def backfill(
    start_date: str,
    end_date: Optional[str],
    batch_size: int,
    metrics: tuple,
) -> None:
    """Backfill historical health data."""
    try:
        # Parse dates
        start = parse_date(start_date)
        end = parse_date(end_date) if end_date else get_yesterday()

        # Validate date range
        if start > end:
            click.echo("❌ Start date must be before end date", err=True)
            sys.exit(1)

        total_days = (end - start).days + 1

        click.echo(f"📚 Historical Backfill")
        click.echo(f"   Start date: {start}")
        click.echo(f"   End date: {end}")
        click.echo(f"   Total days: {total_days}")
        click.echo(f"   Batch size: {batch_size} days")

        if metrics:
            click.echo(f"   Metrics: {', '.join(metrics)}")

        # Confirm large backfills
        if total_days > 90:
            click.confirm(
                f"\n⚠️  This will backfill {total_days} days of data. Continue?",
                abort=True,
            )

        # Initialize sync service
        sync_service = HealthDataSync()

        # Authenticate
        click.echo("\n🔐 Authenticating with Garmin Connect China...")
        sync_service.authenticate()
        click.echo("✅ Authentication successful\n")

        # Perform backfill
        metric_list = list(metrics) if metrics else None
        results = sync_service.backfill_historical(
            start, end, metric_types=metric_list, batch_size=batch_size
        )

        # Display final results
        click.echo("\n📊 Backfill Complete!")
        total_synced = sum(s.get("synced", 0) for s in results.values())
        total_errors = sum(s.get("errors", 0) for s in results.values())

        for metric_type, stats in results.items():
            synced = stats.get("synced", 0)
            errors = stats.get("errors", 0)
            status_icon = "✓" if errors == 0 else "⚠"

            click.echo(
                f"  {status_icon} {metric_type:20} {synced:4} records  "
                f"({errors} errors)" if errors else f"  {status_icon} {metric_type:20} {synced:4} records"
            )

        click.echo(
            f"\n{'✅' if total_errors == 0 else '⚠️ '} "
            f"Total: {total_synced} records synced"
        )

        sys.exit(0 if total_errors == 0 else 1)

    except GarminAuthError as e:
        click.echo(f"\n❌ Authentication failed: {e}", err=True)
        sys.exit(1)
    except Exception as e:
        click.echo(f"\n❌ Backfill failed: {e}", err=True)
        logger.exception("Backfill failed")
        sys.exit(1)


@cli.command()
def sync_incremental() -> None:
    """Perform incremental sync (sync new data since last sync)."""
    try:
        click.echo("🔄 Incremental Sync (syncing new data only)\n")

        # Initialize sync service
        sync_service = HealthDataSync()

        # Authenticate
        click.echo("🔐 Authenticating...")
        sync_service.authenticate()
        click.echo("✅ Authenticated\n")

        # Perform incremental sync
        results = sync_service.sync_incremental()

        # Display results
        click.echo("📊 Sync Results:")
        total_synced = 0
        total_errors = 0

        for metric_type, stats in results.items():
            synced = stats.get("synced", 0)
            errors = stats.get("errors", 0)

            if synced > 0 or errors > 0:
                total_synced += synced
                total_errors += errors

                status_icon = "✓" if errors == 0 else "⚠"
                click.echo(
                    f"  {status_icon} {metric_type:20} {synced:3} new records  "
                    f"({errors} errors)" if errors else f"  {status_icon} {metric_type:20} {synced:3} new records"
                )

        if total_synced == 0:
            click.echo("  ℹ️  All data is up to date!")

        click.echo(
            f"\n{'✅' if total_errors == 0 else '⚠️ '} "
            f"Synced {total_synced} new records"
        )

        sys.exit(0 if total_errors == 0 else 1)

    except GarminAuthError as e:
        click.echo(f"\n❌ Authentication failed: {e}", err=True)
        sys.exit(1)
    except Exception as e:
        click.echo(f"\n❌ Incremental sync failed: {e}", err=True)
        logger.exception("Incremental sync failed")
        sys.exit(1)


if __name__ == "__main__":
    cli()
