"""Configuration management for PlanitAI KPI."""

from __future__ import annotations

import os
from dataclasses import dataclass, field
from enum import Enum
from pathlib import Path
from typing import Any

import yaml
from dotenv import load_dotenv

load_dotenv()


class NodeType(str, Enum):
    """KPI node types."""

    KGI = "kgi"  # Key Goal Indicator (top-level)
    KPI = "kpi"  # Key Performance Indicator (calculated)
    INPUT = "input"  # Input value (leaf node)


class KPICategory(str, Enum):
    """KPI categories."""

    FINANCE = "finance"
    SALES = "sales"
    MARKETING = "marketing"
    HR = "hr"
    PRODUCT = "product"
    CUSTOMER = "customer"
    OPERATION = "operation"


@dataclass
class KPINodeConfig:
    """KPI node configuration."""

    id: str
    name: str
    type: NodeType
    formula: str | None = None
    unit: str = ""
    category: KPICategory = KPICategory.FINANCE
    children: list[str] = field(default_factory=list)
    description: str = ""

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> KPINodeConfig:
        """Create from dictionary."""
        node_type = data.get("type", "input")
        if isinstance(node_type, str):
            node_type = NodeType(node_type.lower())

        category = data.get("category", "finance")
        if isinstance(category, str):
            category = KPICategory(category.lower())

        return cls(
            id=data["id"],
            name=data["name"],
            type=node_type,
            formula=data.get("formula"),
            unit=data.get("unit", ""),
            category=category,
            children=data.get("children", []),
            description=data.get("description", ""),
        )


@dataclass
class PivotConfig:
    """Pivot table format configuration."""

    enabled: bool = False
    period_row: int = 3
    header_row: int = 4
    data_start_row: int = 5
    item_col: int = 1
    data_start_col: int = 4
    cols_per_period: int = 4
    budget_col_offset: int = 0
    actual_col_offset: int = 1
    item_mapping: dict[str, str] = field(default_factory=dict)


@dataclass
class SheetConfig:
    """Google Sheets configuration."""

    sheet_id: str
    data_range: str
    target_range: str | None = None
    period_column: str = "period"
    pivot: PivotConfig = field(default_factory=PivotConfig)


@dataclass
class Config:
    """Main configuration."""

    sheet: SheetConfig
    tree: list[KPINodeConfig]
    gemini_api_key: str
    output_path: str = "./output"
    language: str = "ja"
    credentials_path: str = "credentials.json"

    @classmethod
    def from_yaml(cls, path: str | Path) -> Config:
        """Load configuration from YAML file."""
        path = Path(path)

        with open(path, encoding="utf-8") as f:
            data = yaml.safe_load(f)

        # Environment variable substitution
        gemini_api_key = data.get("gemini_api_key", "")
        if gemini_api_key.startswith("${") and gemini_api_key.endswith("}"):
            env_var = gemini_api_key[2:-1]
            gemini_api_key = os.environ.get(env_var, "")

        # Sheet config
        sheet_data = data.get("sheet", {})

        # Pivot config
        pivot_data = sheet_data.get("pivot", {})
        pivot_config = PivotConfig(
            enabled=pivot_data.get("enabled", False),
            period_row=pivot_data.get("period_row", 3),
            header_row=pivot_data.get("header_row", 4),
            data_start_row=pivot_data.get("data_start_row", 5),
            item_col=pivot_data.get("item_col", 1),
            data_start_col=pivot_data.get("data_start_col", 4),
            cols_per_period=pivot_data.get("cols_per_period", 4),
            budget_col_offset=pivot_data.get("budget_col_offset", 0),
            actual_col_offset=pivot_data.get("actual_col_offset", 1),
            item_mapping=pivot_data.get("item_mapping", {}),
        )

        sheet_config = SheetConfig(
            sheet_id=sheet_data.get("sheet_id", ""),
            data_range=sheet_data.get("data_range", ""),
            target_range=sheet_data.get("target_range"),
            period_column=sheet_data.get("period_column", "period"),
            pivot=pivot_config,
        )

        # Tree config
        tree_nodes = [KPINodeConfig.from_dict(node) for node in data.get("tree", [])]

        return cls(
            sheet=sheet_config,
            tree=tree_nodes,
            gemini_api_key=gemini_api_key,
            output_path=data.get("output_path", "./output"),
            language=data.get("language", "ja"),
            credentials_path=data.get("credentials_path", "credentials.json"),
        )

    def validate(self, skip_ai: bool = False) -> list[str]:
        """Validate configuration.

        Args:
            skip_ai: If True, skip AI-related validation.
        """
        errors = []

        if not self.sheet.sheet_id:
            errors.append("sheet.sheet_id is required")

        if not self.sheet.data_range:
            errors.append("sheet.data_range is required")

        if not skip_ai and not self.gemini_api_key:
            errors.append("gemini_api_key is required (set GEMINI_API_KEY environment variable)")

        if not self.tree:
            errors.append("At least one KPI node is required in tree")

        # Check for KGI node
        kgi_nodes = [n for n in self.tree if n.type == NodeType.KGI]
        if not kgi_nodes:
            errors.append("At least one KGI node is required")
        elif len(kgi_nodes) > 1:
            errors.append("Only one KGI node is allowed")

        # Check for duplicate IDs
        ids = [n.id for n in self.tree]
        if len(ids) != len(set(ids)):
            errors.append("Duplicate node IDs found")

        return errors
