import re
import json
import pandas as pd
from typing import Dict, Any, Union
from .exceptions import PFXParseError, PFXSchemaError
from .utils import validate_pfx

def parse_schema(schema_section: str) -> Dict[str, str]:
    """Parse the schema section into a dictionary"""
    schema = {}
    for line in schema_section.split('\n'):
        line = line.strip()
        if not line or line.startswith('#'):
            continue
        try:
            field_name, field_type = line.split(':')
            schema[field_name.strip()] = field_type.strip()
        except ValueError:
            raise PFXParseError(f"Invalid schema line: {line}")
    return schema

def parse_data(data_section: str, schema: Dict[str, str]) -> Dict[str, list]:
    """Parse the data section into a dictionary of columns"""
    data = {field: [] for field in schema}
    lines = [line.strip() for line in data_section.split('\n') if line.strip() and not line.startswith('#')]

    for line in lines:
        # Remove comments
        line = re.sub(r'#.*$', '', line).strip()
        if not line:
            continue

        # Parse values
        values = []
        current = ""
        in_quotes = False
        escape = False

        for char in line:
            if escape:
                current += char
                escape = False
            elif char == '\\':
                escape = True
            elif char == '"':
                in_quotes = not in_quotes
                current += char
            elif char == ',' and not in_quotes:
                values.append(current.strip())
                current = ""
            else:
                current += char

        if current:
            values.append(current.strip())

        if len(values) != len(schema):
            raise PFXParseError(f"Row has {len(values)} values but schema expects {len(schema)}")

        # Convert values based on schema
        for (field, field_type), value in zip(schema.items(), values):
            try:
                if field_type.startswith('list['):
                    # Parse list
                    inner_type = field_type[5:-1]
                    if value.startswith('[') and value.endswith(']'):
                        items = json.loads(value)
                        converted = [convert_value(inner_type, item) for item in items]
                    else:
                        raise PFXParseError(f"Invalid list format for {field}: {value}")
                elif field_type.startswith('dict'):
                    # Parse dict
                    if value.startswith('{') and value.endswith('}'):
                        converted = json.loads(value)
                    else:
                        raise PFXParseError(f"Invalid dict format for {field}: {value}")
                else:
                    # Parse primitive type
                    converted = convert_value(field_type, value)
                data[field].append(converted)
            except Exception as e:
                raise PFXParseError(f"Error converting {field} ({field_type}) with value {value}: {str(e)}")

    return data

def convert_value(field_type: str, value: str) -> Any:
    """Convert a string value to the appropriate Python type"""
    if value.lower() == 'true':
        return True
    elif value.lower() == 'false':
        return False
    elif value.lower() == 'null':
        return None

    if field_type == 'str':
        return value.strip('"')
    elif field_type == 'int32':
        return int(value)
    elif field_type == 'int64':
        return int(value)
    elif field_type == 'float32' or field_type == 'float64':
        return float(value)
    elif field_type == 'bool':
        return value.lower() == 'true'
    else:
        raise PFXParseError(f"Unsupported type: {field_type}")

def read_pfx(file_path: str) -> pd.DataFrame:
    """
    Read a PandaFlex file into a pandas DataFrame

    Args:
        file_path: Path to the PFX file

    Returns:
        pandas.DataFrame containing the data
    """
    # Validate the file first
    if not validate_pfx(file_path):
        raise PFXParseError("Invalid PFX file structure")

    with open(file_path, 'r') as f:
        content = f.read()

    # Split into sections
    sections = {}
    current_section = None

    for line in content.split('\n'):
        line = line.strip()
        if line.startswith('#'):
            continue
        elif line.startswith('[') and line.endswith(']'):
            current_section = line[1:-1]
            sections[current_section] = []
        elif current_section:
            sections[current_section].append(line)

    if 'Schema' not in sections or 'Data' not in sections:
        raise PFXParseError("Missing required sections in PFX file")

    # Parse schema
    schema = parse_schema('\n'.join(sections['Schema']))

    # Parse data
    data = parse_data('\n'.join(sections['Data']), schema)

    # Create DataFrame
    df = pd.DataFrame(data)

    # Parse metadata if exists
    if 'Metadata' in sections:
        metadata_str = '\n'.join(sections['Metadata'])
        try:
            metadata = json.loads(metadata_str)
            df.attrs['pandaflex_metadata'] = metadata
        except json.JSONDecodeError:
            pass

    return df