"""FreeStyle Libre 3 CGM export format schema definition.

This module defines the specific schema for FreeStyle Libre 3 CGM data format,
including raw file column definitions, record types, and metadata structure.

File structure:
- Line 1: Metadata row (Glucose Data, Generated on, timestamp, Generated by, name)
- Line 2: Column headers
- Line 3+: Data rows with glucose readings and events

Example first line:
Glucose Data,Generated on,11-12-2024 09:40 UTC,Generated by,USER_NAME

Example data row:
FreeStyle Libre 3,2A404063-0DB9-49F2-B234-9FD9FE48DBA6,11-11-2024 21:35,0,107,,,,,,,,,,,,,,

Record Type encoding:
    0 = Computed/passive collected every 15 minutes, only stores the last 8 hours ("Historic Glucose" column)
    1 = Manual scanned ("Scan Glucose" column)
    2 = Strip glucose (finger prick calibration)
    3 = TBD (to be determined)
    4 = Insulin consumption ("Rapid-Acting Insulin (units)" and "Long-Acting Insulin Value (units)" columns)
    5 = Logged food consumption ("Carbohydrates (grams)" column)
    6 = Usually blank, but also other things logged by the user like Comments and Exercise
"""

from typing import List
from enum import Enum
import polars as pl
from cgm_format.interface.schema import (
    ColumnSchema,
    CGMSchemaDefinition,
    EnumLiteral,
)

# =============================================================================
# File Format Constants
# =============================================================================

# File structure: Row 1 = metadata, Row 2 = header, Row 3+ = data
LIBRE_HEADER_LINE = 2
LIBRE_DATA_START_LINE = 3
LIBRE_METADATA_LINES = (1,)  # Row 1 is metadata to skip

# Multiple timestamp formats across Libre versions (tuple for probing)
LIBRE_TIMESTAMP_FORMATS = (
    "%d-%m-%Y %H:%M",  # European Libre format: 22-11-2024 17:55
    "%m-%d-%Y %H:%M",  # US Libre format: 11-22-2024 21:35
)

# Format detection patterns (unique identifiers in CSV headers/content)
LIBRE_DETECTION_PATTERNS = [
    "Glucose Data,Generated",           # First line metadata pattern
    "Historic Glucose mg/dL",           # Libre-specific column
    "FreeStyle Libre",                  # Device name in data rows
    "Serial Number,Device Timestamp",   # Unique column combination
]


# =============================================================================
# Libre Record Type Enums
# =============================================================================

class LibreRecordType(int, Enum):
    """Type of recorded event in FreeStyle Libre data (Record Type column)."""
    HISTORIC_GLUCOSE = 0  # Automatic CGM reading (Historic Glucose column)
    SCAN_GLUCOSE = 1      # Manual scan reading (Scan Glucose column)
    STRIP_GLUCOSE = 2     # Finger prick calibration (Strip Glucose column)
    UNKNOWN = 3           # Unknown/undocumented type
    INSULIN = 4           # Insulin dose (Rapid/Long-Acting columns)
    FOOD = 5              # Food/carb intake (Carbohydrates column)
    OTHER = 6             # Notes, exercise, other user logs


# =============================================================================
# Raw File Column Names (as they appear in Libre CSV exports)
# =============================================================================

class LibreColumn(EnumLiteral):
    """Column names in FreeStyle Libre 3 export files."""
    DEVICE = "Device"
    SERIAL_NUMBER = "Serial Number"
    DEVICE_TIMESTAMP = "Device Timestamp"
    RECORD_TYPE = "Record Type"
    HISTORIC_GLUCOSE = "Historic Glucose mg/dL"
    SCAN_GLUCOSE = "Scan Glucose mg/dL"
    NON_NUMERIC_RAPID_INSULIN = "Non-numeric Rapid-Acting Insulin"
    RAPID_INSULIN = "Rapid-Acting Insulin (units)"
    NON_NUMERIC_FOOD = "Non-numeric Food"
    CARBOHYDRATES_GRAMS = "Carbohydrates (grams)"
    CARBOHYDRATES_SERVINGS = "Carbohydrates (servings)"
    NON_NUMERIC_LONG_INSULIN = "Non-numeric Long-Acting Insulin"
    LONG_INSULIN = "Long-Acting Insulin Value (units)"
    NOTES = "Notes"
    STRIP_GLUCOSE = "Strip Glucose mg/dL"
    KETONE = "Ketone mmol/L"
    MEAL_INSULIN = "Meal Insulin (units)"
    CORRECTION_INSULIN = "Correction Insulin (units)"
    USER_CHANGE_INSULIN = "User Change Insulin (units)"
    
    @classmethod
    def get_all_columns(cls) -> List[str]:
        """Get all column names in order."""
        return [
            cls.DEVICE, cls.SERIAL_NUMBER, cls.DEVICE_TIMESTAMP, cls.RECORD_TYPE,
            cls.HISTORIC_GLUCOSE, cls.SCAN_GLUCOSE, cls.NON_NUMERIC_RAPID_INSULIN,
            cls.RAPID_INSULIN, cls.NON_NUMERIC_FOOD, cls.CARBOHYDRATES_GRAMS,
            cls.CARBOHYDRATES_SERVINGS, cls.NON_NUMERIC_LONG_INSULIN, cls.LONG_INSULIN,
            cls.NOTES, cls.STRIP_GLUCOSE, cls.KETONE, cls.MEAL_INSULIN,
            cls.CORRECTION_INSULIN, cls.USER_CHANGE_INSULIN
        ]


# =============================================================================
# FreeStyle Libre 3 Raw File Format Schema
# =============================================================================

LIBRE_SCHEMA = CGMSchemaDefinition(
    service_columns=(
        {
            "name": LibreColumn.DEVICE,
            "dtype": pl.Utf8,
            "description": "Device model name (e.g., 'FreeStyle Libre 3')",
            "constraints": {"required": True}
        },
        {
            "name": LibreColumn.SERIAL_NUMBER,
            "dtype": pl.Utf8,
            "description": "Device serial number/UUID",
            "constraints": {"required": True}
        },
        {
            "name": LibreColumn.DEVICE_TIMESTAMP,
            "dtype": pl.Utf8,  # String format: "MM-DD-YYYY HH:MM"
            "description": "Timestamp of the event in MM-DD-YYYY HH:MM format",
            "constraints": {"required": True}
        },
        {
            "name": LibreColumn.RECORD_TYPE,
            "dtype": pl.Int64,
            "description": "Type of record (0=Historic, 1=Scan, 2=Strip, 4=Insulin, 5=Food, 6=Other)",
            "constraints": {
                "required": True,
                "enum": [e.value for e in LibreRecordType]
            }
        },
    ),
    data_columns=(
        # Column order must match the exact CSV file structure
        {
            "name": LibreColumn.HISTORIC_GLUCOSE,
            "dtype": pl.Float64,
            "description": "Automatic CGM reading (recorded every 15 minutes, last 8 hours only)",
            "unit": "mg/dL",
            "constraints": {"minimum": 0}
        },
        {
            "name": LibreColumn.SCAN_GLUCOSE,
            "dtype": pl.Float64,
            "description": "Manual scan glucose reading",
            "unit": "mg/dL",
            "constraints": {"minimum": 0}
        },
        {
            "name": LibreColumn.NON_NUMERIC_RAPID_INSULIN,
            "dtype": pl.Utf8,
            "description": "Non-numeric rapid-acting insulin notes",
            "constraints": {"required": False}
        },
        {
            "name": LibreColumn.RAPID_INSULIN,
            "dtype": pl.Float64,
            "description": "Rapid-acting (bolus) insulin dose",
            "unit": "units",
            "constraints": {"minimum": 0}
        },
        {
            "name": LibreColumn.NON_NUMERIC_FOOD,
            "dtype": pl.Utf8,
            "description": "Non-numeric food notes",
            "constraints": {"required": False}
        },
        {
            "name": LibreColumn.CARBOHYDRATES_GRAMS,
            "dtype": pl.Float64,
            "description": "Carbohydrate intake",
            "unit": "grams",
            "constraints": {"minimum": 0}
        },
        {
            "name": LibreColumn.CARBOHYDRATES_SERVINGS,
            "dtype": pl.Float64,
            "description": "Carbohydrate intake in servings",
            "unit": "servings",
            "constraints": {"minimum": 0}
        },
        {
            "name": LibreColumn.NON_NUMERIC_LONG_INSULIN,
            "dtype": pl.Utf8,
            "description": "Non-numeric long-acting insulin notes",
            "constraints": {"required": False}
        },
        {
            "name": LibreColumn.LONG_INSULIN,
            "dtype": pl.Float64,
            "description": "Long-acting (basal) insulin dose",
            "unit": "units",
            "constraints": {"minimum": 0}
        },
        {
            "name": LibreColumn.NOTES,
            "dtype": pl.Utf8,
            "description": "User notes and comments",
            "constraints": {"required": False}
        },
        {
            "name": LibreColumn.STRIP_GLUCOSE,
            "dtype": pl.Float64,
            "description": "Finger prick calibration glucose reading",
            "unit": "mg/dL",
            "constraints": {"minimum": 0}
        },
        {
            "name": LibreColumn.KETONE,
            "dtype": pl.Float64,
            "description": "Ketone level measurement",
            "unit": "mmol/L",
            "constraints": {"minimum": 0}
        },
        {
            "name": LibreColumn.MEAL_INSULIN,
            "dtype": pl.Float64,
            "description": "Meal-time insulin dose",
            "unit": "units",
            "constraints": {"minimum": 0}
        },
        {
            "name": LibreColumn.CORRECTION_INSULIN,
            "dtype": pl.Float64,
            "description": "Correction insulin dose",
            "unit": "units",
            "constraints": {"minimum": 0}
        },
        {
            "name": LibreColumn.USER_CHANGE_INSULIN,
            "dtype": pl.Float64,
            "description": "User-defined insulin change",
            "unit": "units",
            "constraints": {"minimum": 0}
        },
    ),
    header_line=LIBRE_HEADER_LINE,
    data_start_line=LIBRE_DATA_START_LINE,
    metadata_lines=LIBRE_METADATA_LINES
)





# =============================================================================
# Schema JSON Export Helper
# =============================================================================

def regenerate_schema_json() -> None:
    """Regenerate libre.json from the current schema definition.
    
    Run this after modifying enums or schema to keep libre.json in sync:
        python3 -c "from formats.libre import regenerate_schema_json; regenerate_schema_json()"
    """
    from cgm_format.interface.schema import regenerate_schema_json as _regenerate
    _regenerate(LIBRE_SCHEMA, __file__)





