"""Export command - sync YAML files back to Anki."""

from dataclasses import dataclass, field
import logging
from typing import List, Tuple

import click

from ..anki_client import AnkiClient, AnkiConnectError
from ..file_manager import FileManager
from .common import (
    log_and_print_connect_error,
    log_and_print_unexpected_error,
    temporary_log_level,
)

logger = logging.getLogger(__name__)


@dataclass
class ExportStats:
    """Tracking counters for export operations."""

    updated: int = 0
    created: int = 0
    errors: int = 0
    failed_notes: List[Tuple[int, str]] = field(default_factory=list)


def _update_note_id_in_yaml_files(
    file_manager: FileManager,
    note_id: int,
    new_id: int,
) -> None:
    yaml_files = file_manager.get_all_yaml_files()
    for yaml_file in yaml_files:
        loaded_note = file_manager.load_note(yaml_file)
        if loaded_note and loaded_note.id == note_id:
            if file_manager.update_note_id_in_file(yaml_file, new_id):
                logger.debug(
                    "Updated YAML file %s with new ID %s",
                    yaml_file,
                    new_id,
                )
            break


def _sync_note(
    client: AnkiClient,
    file_manager: FileManager,
    note,
    deck_name: str,
    stats: ExportStats,
) -> None:
    note_id = note.id
    if note_id and note_id > 0 and client.note_exists(note_id):
        client.update_note(note_id, fields=note.fields, tags=note.tags)
        if note.deck:
            current_deck = client.get_note_deck(note_id)
            if current_deck != note.deck:
                client.move_note_to_deck(note_id, note.deck)
        stats.updated += 1
        logger.debug("Updated note %s", note_id)
        return

    target_deck = note.deck or deck_name
    new_note_data = {
        "deckName": target_deck,
        "modelName": note.type,
        "fields": note.fields,
        "tags": note.tags,
    }
    new_id = client.add_note(new_note_data)
    if note_id and note_id > 0:
        _update_note_id_in_yaml_files(file_manager, note_id, new_id)
    else:
        _update_note_id_in_yaml_files(file_manager, 0, new_id)
    stats.created += 1
    logger.debug("Created note with ID %s", new_id)


def _print_summary(note_count: int, stats: ExportStats) -> None:
    print(f"✓ Synced {note_count} notes")
    print(f"  - Updated: {stats.updated}")
    print(f"  - Created: {stats.created}")
    if stats.errors > 0:
        print(f"⚠ {stats.errors} notes failed to sync:")
        for note_id, error in stats.failed_notes:
            print(f"    - Note {note_id}: {error}")


def export_notes(input_dir: str = "notes", deck_name: str = "Default") -> None:
    """Export/sync notes from YAML files back to Anki.

    Args:
        input_dir: Directory containing YAML files
        deck_name: Deck to add new notes to (for notes without existing IDs)

    Raises:
        AnkiConnectError: If connection to Anki fails
    """
    client = AnkiClient()
    file_manager = FileManager(input_dir)
    stats = ExportStats()

    try:
        notes = file_manager.get_all_notes()
        if not notes:
            logger.info("No YAML files found to export")
            print("✓ No notes to export")
            return
        progress_label = f'Exporting notes from "{input_dir}" directory to Anki'
        with temporary_log_level("anki_sync", logging.WARNING):
            with click.progressbar(notes, label=progress_label) as progress_notes:
                for note in progress_notes:
                    try:
                        _sync_note(client, file_manager, note, deck_name, stats)
                    except AnkiConnectError as e:
                        logger.error("Failed to sync note %s: %s", note.id, e)
                        stats.failed_notes.append((note.id, str(e)))
                        stats.errors += 1
                    except Exception as e:  # pylint: disable=broad-exception-caught
                        logger.error(
                            "Unexpected error syncing note %s: %s",
                            note.id,
                            e,
                        )
                        stats.failed_notes.append((note.id, str(e)))
                        stats.errors += 1

        _print_summary(len(notes), stats)
    except AnkiConnectError as e:
        log_and_print_connect_error(logger, e)
        raise
    except Exception as e:
        log_and_print_unexpected_error(logger, e, "export")
        raise
