"""Dataset metadata management service."""

import yaml
from datetime import datetime
from pathlib import Path
from typing import List, Optional

from ..s3_data_service import S3DataService
from .models import BasicMetadata


class DatasetMetadataService:
    """Manages dataset metadata operations."""

    def __init__(self, s3_service: S3DataService):
        self.s3_service = s3_service

    def get_basic_metadata(self, dataset_id: str) -> BasicMetadata:
        """Get basic metadata for a dataset, with graceful fallback for legacy datasets."""
        metadata_path = f"czbillgen/datasets/{dataset_id}/_metadata.yaml"

        try:
            metadata_content = self.s3_service.read_text_file(metadata_path)
            metadata_dict = yaml.safe_load(metadata_content)

            # Always dynamically check stages, ignore any stored stages_completed
            current_stages = self._infer_completed_stages(dataset_id)

            return BasicMetadata(
                dataset_id=metadata_dict["dataset_id"],
                created_at=datetime.fromisoformat(metadata_dict["created_at"].replace('Z', '+00:00')),
                description=metadata_dict["description"],
                reference_data_version=metadata_dict.get("reference_data_version", "Unknown"),
                stages_completed=current_stages,  # Always use dynamically checked stages
                last_updated=datetime.fromisoformat(metadata_dict["last_updated"].replace('Z', '+00:00'))
            )
        except Exception:
            # Legacy dataset - infer what we can
            return self._create_legacy_metadata(dataset_id)

    def _create_legacy_metadata(self, dataset_id: str) -> BasicMetadata:
        """Create basic metadata for legacy datasets."""
        # Infer creation date from dataset_id timestamp
        try:
            # Format: 2025-01-15_14-30-22
            date_part, time_part = dataset_id.split('_')
            year, month, day = date_part.split('-')
            hour, minute, second = time_part.split('-')
            created_at = datetime(int(year), int(month), int(day), int(hour), int(minute), int(second))
        except (ValueError, IndexError):
            created_at = datetime.now()

        # Infer completed stages by checking what folders exist
        stages_completed = self._infer_completed_stages(dataset_id)

        return BasicMetadata(
            dataset_id=dataset_id,
            created_at=created_at,
            description="No description available (legacy dataset)",
            reference_data_version="Unknown",
            stages_completed=stages_completed,
            last_updated=created_at
        )

    def _infer_completed_stages(self, dataset_id: str) -> List[str]:
        """Infer completed stages by checking folder existence and file content."""
        possible_stages = ["generate", "k8s", "metadata", "usage", "discount", "tax"]
        completed = []

        for stage in possible_stages:
            if self._check_stage_completion(dataset_id, stage):
                completed.append(stage)

        return completed

    def _check_stage_completion(self, dataset_id: str, stage: str) -> bool:
        """Check if a stage is completed by examining its S3 folder for meaningful content."""
        stage_path = f"czbillgen/datasets/{dataset_id}/{stage}/"

        try:
            # Check if stage folder has any files
            files = self.s3_service.list_files(stage_path, max_files=10)  # Check first 10 files

            if not files:
                return False

            # Filter out common non-data files
            data_files = [
                f for f in files
                if not f.endswith(('/_SUCCESS', '/SUCCESS', '/.DS_Store'))
                and '/.' not in f  # Skip hidden files
                and f != stage_path  # Skip the folder itself
            ]

            # Stage is complete if it has any meaningful data files
            return len(data_files) > 0

        except Exception:
            return False

    def update_basic_metadata(self, dataset_id: str, **kwargs) -> None:
        """Update basic metadata fields."""
        metadata = self.get_basic_metadata(dataset_id)

        # Update fields if provided
        if "description" in kwargs:
            metadata.description = kwargs["description"]
        if "reference_data_version" in kwargs:
            metadata.reference_data_version = kwargs["reference_data_version"]

        metadata.last_updated = datetime.now()

        self._save_basic_metadata(dataset_id, metadata)

    def create_initial_metadata(self, dataset_id: str, description: str, reference_data_version: str = "Unknown") -> None:
        """Create initial metadata for a new dataset."""
        now = datetime.now()
        metadata = BasicMetadata(
            dataset_id=dataset_id,
            created_at=now,
            description=description,
            reference_data_version=reference_data_version,
            stages_completed=[],  # Will be dynamically calculated
            last_updated=now
        )

        self._save_basic_metadata(dataset_id, metadata)

    def _save_basic_metadata(self, dataset_id: str, metadata: BasicMetadata) -> None:
        """Save basic metadata to S3 (excluding stages_completed which is dynamically calculated)."""
        metadata_path = f"czbillgen/datasets/{dataset_id}/_metadata.yaml"

        metadata_dict = {
            "dataset_id": metadata.dataset_id,
            "created_at": metadata.created_at.isoformat() + "Z",
            "description": metadata.description,
            "reference_data_version": metadata.reference_data_version,
            # Note: stages_completed is not stored - it's calculated dynamically
            "last_updated": metadata.last_updated.isoformat() + "Z"
        }

        yaml_content = yaml.dump(metadata_dict, default_flow_style=False, sort_keys=True)
        self.s3_service.upload_text_content(metadata_path, yaml_content)

    def list_datasets(self) -> List[BasicMetadata]:
        """List all datasets with basic metadata."""
        dataset_prefix = "czbillgen/datasets/"

        try:
            folders = self.s3_service.list_folders(dataset_prefix)
            datasets = []

            for folder in folders:
                # Extract dataset_id from folder path
                dataset_id = folder.rstrip('/').split('/')[-1]
                if dataset_id:  # Skip empty folder names
                    metadata = self.get_basic_metadata(dataset_id)
                    datasets.append(metadata)

            # Sort by creation date, newest first
            # Handle mixed timezone-aware and timezone-naive datetimes
            def sort_key(dataset):
                dt = dataset.created_at
                # Convert timezone-aware to naive for consistent comparison
                if dt.tzinfo is not None:
                    dt = dt.replace(tzinfo=None)
                return dt

            return sorted(datasets, key=sort_key, reverse=True)

        except Exception:
            return []

    def dataset_exists(self, dataset_id: str) -> bool:
        """Check if a dataset exists."""
        dataset_path = f"czbillgen/datasets/{dataset_id}/"
        try:
            files = self.s3_service.list_files(dataset_path, max_files=1)
            return len(files) > 0
        except Exception:
            return False