"""
Reporting System Types Module
Defines data structures for report generation and configuration
"""

from dataclasses import dataclass, field
from datetime import datetime
from typing import List, Optional, Dict, Any, Literal
from enum import Enum


class ReportFormat(str, Enum):
    """Supported report output formats"""
    HTML = "html"
    MARKDOWN = "markdown"
    JSON = "json"
    CSV = "csv"
    TEXT = "text"


class ReportType(str, Enum):
    """Types of reports that can be generated"""
    PNL_SUMMARY = "pnl_summary"
    POSITION_STATUS = "position_status"
    STRATEGY_ANALYSIS = "strategy_analysis"
    ALERT_HISTORY = "alert_history"
    TRADE_HISTORY = "trade_history"
    PERFORMANCE_OVERVIEW = "performance_overview"
    RISK_ASSESSMENT = "risk_assessment"
    DAILY_SUMMARY = "daily_summary"
    WEEKLY_SUMMARY = "weekly_summary"
    MONTHLY_SUMMARY = "monthly_summary"
    CUSTOM = "custom"


class ReportPeriod(str, Enum):
    """Time periods for report data"""
    TODAY = "today"
    YESTERDAY = "yesterday"
    LAST_7_DAYS = "last_7_days"
    LAST_30_DAYS = "last_30_days"
    LAST_90_DAYS = "last_90_days"
    THIS_WEEK = "this_week"
    THIS_MONTH = "this_month"
    THIS_YEAR = "this_year"
    ALL_TIME = "all_time"
    CUSTOM = "custom"


@dataclass
class ChartConfig:
    """
    Configuration for charts in reports
    
    Attributes:
        chart_type: Type of chart (line, bar, pie, etc.)
        title: Chart title
        width: Chart width in pixels
        height: Chart height in pixels
        show_legend: Whether to show legend
        colors: Custom color palette
        data_labels: Show data labels on chart
    """
    chart_type: Literal["line", "bar", "pie", "area", "scatter"] = "line"
    title: str = ""
    width: int = 800
    height: int = 400
    show_legend: bool = True
    colors: List[str] = field(default_factory=lambda: [
        "#4CAF50", "#F44336", "#2196F3", "#FF9800", "#9C27B0",
        "#00BCD4", "#FFEB3B", "#795548", "#607D8B", "#E91E63"
    ])
    data_labels: bool = False
    
    def __post_init__(self):
        """Validate chart configuration"""
        if self.width <= 0:
            raise ValueError(f"Chart width must be positive, got {self.width}")
        if self.height <= 0:
            raise ValueError(f"Chart height must be positive, got {self.height}")


@dataclass
class ReportConfig:
    """
    Configuration for report generation
    
    Attributes:
        report_type: Type of report to generate
        format: Output format
        period: Time period for data
        title: Report title
        subtitle: Report subtitle
        author: Report author name
        include_charts: Whether to include charts
        include_recommendations: Whether to include recommendations
        include_raw_data: Whether to include raw data tables
        custom_start_date: Custom period start (if period is CUSTOM)
        custom_end_date: Custom period end (if period is CUSTOM)
        chart_config: Chart configuration
        custom_sections: Additional custom sections
        logo_path: Path to logo image
        theme: Report theme (light/dark)
    """
    report_type: ReportType = ReportType.PERFORMANCE_OVERVIEW
    format: ReportFormat = ReportFormat.HTML
    period: ReportPeriod = ReportPeriod.LAST_30_DAYS
    title: str = "Trading Report"
    subtitle: str = ""
    author: str = "Hyperliquid Monitor Plus"
    include_charts: bool = True
    include_recommendations: bool = True
    include_raw_data: bool = False
    custom_start_date: Optional[datetime] = None
    custom_end_date: Optional[datetime] = None
    chart_config: Optional[ChartConfig] = None
    custom_sections: List[str] = field(default_factory=list)
    logo_path: Optional[str] = None
    theme: Literal["light", "dark"] = "light"
    
    def __post_init__(self):
        """Validate configuration"""
        if self.period == ReportPeriod.CUSTOM:
            if not self.custom_start_date or not self.custom_end_date:
                raise ValueError(
                    "custom_start_date and custom_end_date are required "
                    "when period is CUSTOM"
                )
            if self.custom_start_date > self.custom_end_date:
                raise ValueError(
                    "custom_start_date must be before custom_end_date"
                )


@dataclass
class ReportData:
    """
    Data container for report generation
    
    Attributes:
        pnl_summary: PnL summary data
        positions: Current positions data
        strategy_metrics: Strategy analysis metrics
        alerts: Alert history
        trades: Trade history
        equity_curve: Equity curve data points
        performance_by_coin: Performance breakdown by coin
        performance_by_time: Performance breakdown by time
        recommendations: List of recommendations
        statistics: General statistics
        metadata: Additional metadata
    """
    pnl_summary: Optional[Dict[str, Any]] = None
    positions: Optional[List[Dict[str, Any]]] = None
    strategy_metrics: Optional[Dict[str, Any]] = None
    alerts: Optional[List[Dict[str, Any]]] = None
    trades: Optional[List[Dict[str, Any]]] = None
    equity_curve: Optional[List[float]] = None
    performance_by_coin: Optional[Dict[str, float]] = None
    performance_by_time: Optional[Dict[str, float]] = None
    recommendations: Optional[List[Dict[str, Any]]] = None
    statistics: Optional[Dict[str, Any]] = None
    metadata: Dict[str, Any] = field(default_factory=dict)
    
    @property
    def has_pnl_data(self) -> bool:
        """Check if PnL data is available"""
        return self.pnl_summary is not None
    
    @property
    def has_position_data(self) -> bool:
        """Check if position data is available"""
        return self.positions is not None and len(self.positions) > 0
    
    @property
    def has_strategy_data(self) -> bool:
        """Check if strategy data is available"""
        return self.strategy_metrics is not None
    
    @property
    def has_alert_data(self) -> bool:
        """Check if alert data is available"""
        return self.alerts is not None and len(self.alerts) > 0
    
    @property
    def has_trade_data(self) -> bool:
        """Check if trade data is available"""
        return self.trades is not None and len(self.trades) > 0


@dataclass
class GeneratedReport:
    """
    A generated report ready for output
    
    Attributes:
        config: Configuration used to generate this report
        content: Report content (format depends on output format)
        generated_at: When the report was generated
        data_period_start: Start of data period
        data_period_end: End of data period
        file_path: Path where report was saved (if saved)
        charts: Generated chart data (for HTML reports)
        warnings: Any warnings during generation
        error: Error message if generation failed
    """
    config: ReportConfig
    content: str = ""
    generated_at: datetime = field(default_factory=datetime.now)
    data_period_start: Optional[datetime] = None
    data_period_end: Optional[datetime] = None
    file_path: Optional[str] = None
    charts: List[Dict[str, Any]] = field(default_factory=list)
    warnings: List[str] = field(default_factory=list)
    error: Optional[str] = None
    
    @property
    def is_successful(self) -> bool:
        """Check if report was generated successfully"""
        return self.error is None and len(self.content) > 0
    
    @property
    def format_extension(self) -> str:
        """Get file extension for this report format"""
        extensions = {
            ReportFormat.HTML: ".html",
            ReportFormat.MARKDOWN: ".md",
            ReportFormat.JSON: ".json",
            ReportFormat.CSV: ".csv",
            ReportFormat.TEXT: ".txt"
        }
        return extensions.get(self.config.format, ".txt")
    
    def save(self, file_path: str) -> bool:
        """
        Save report to file
        
        Args:
            file_path: Path to save the report
            
        Returns:
            True if saved successfully, False otherwise
        """
        try:
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(self.content)
            self.file_path = file_path
            return True
        except Exception as e:
            self.warnings.append(f"Failed to save report: {str(e)}")
            return False
    
    def get_summary(self) -> str:
        """Get a brief summary of the report"""
        status = "Success" if self.is_successful else f"Failed: {self.error}"
        return (
            f"Report: {self.config.title}\n"
            f"Type: {self.config.report_type.value}\n"
            f"Format: {self.config.format.value}\n"
            f"Status: {status}\n"
            f"Generated: {self.generated_at.strftime('%Y-%m-%d %H:%M:%S')}\n"
            f"Content Length: {len(self.content)} characters"
        )


@dataclass
class TableData:
    """
    Data for generating tables in reports
    
    Attributes:
        headers: Column headers
        rows: Table rows (list of lists)
        title: Optional table title
        footer: Optional footer text
        alignment: Column alignments (left, center, right)
    """
    headers: List[str]
    rows: List[List[Any]]
    title: str = ""
    footer: str = ""
    alignment: List[str] = field(default_factory=list)
    
    def __post_init__(self):
        """Validate table data"""
        if not self.alignment:
            self.alignment = ["left"] * len(self.headers)
        elif len(self.alignment) != len(self.headers):
            raise ValueError(
                f"Alignment count ({len(self.alignment)}) must match "
                f"header count ({len(self.headers)})"
            )
    
    @property
    def row_count(self) -> int:
        """Get number of rows"""
        return len(self.rows)
    
    @property
    def column_count(self) -> int:
        """Get number of columns"""
        return len(self.headers)


@dataclass
class SectionData:
    """
    Data for a report section
    
    Attributes:
        title: Section title
        content: Section content (text or data)
        section_type: Type of section (text, table, chart, list)
        level: Heading level (1-6)
        table: Table data if section_type is table
        chart: Chart configuration if section_type is chart
        items: List items if section_type is list
    """
    title: str
    content: str = ""
    section_type: Literal["text", "table", "chart", "list", "metric"] = "text"
    level: int = 2
    table: Optional[TableData] = None
    chart: Optional[ChartConfig] = None
    items: List[str] = field(default_factory=list)
    metric_value: Optional[Any] = None
    metric_unit: str = ""
    
    def __post_init__(self):
        """Validate section data"""
        if not 1 <= self.level <= 6:
            raise ValueError(f"Heading level must be 1-6, got {self.level}")
