"""
项目数据推送相关schema
"""

from typing import List, Optional

from fastapi import HTTPException
from pydantic import Field, BaseModel, field_validator
from ..common.push_system import BaseUpdateRequestSchema
from ..common.base import BaseResponseWithID
from ..common.datetime import get_current_date
from ..common.validators import DateStr
from .enums import ProgressType, KeyConstraints, DBTCSCORE

class ProjectResponseBase(BaseResponseWithID):
    """
    项目基础信息, 复制自project_model
    不进行继承，通过检查器确保字段和模型一致
    """
    # 基础信息-不允许更改
    id : str = Field(..., description="项目ID", examples=["uuid"])
    project_type: str = Field("", description="项目类型")
    region_name: List[str] = Field(default_factory=list, description="项目所属区域名称", examples=[["华东", "江苏"]])
    region_path: List[str] = Field(default_factory=list, description="项目所属区域路径", examples=[["110000", "120000", "120001"]])
    province: str = Field("", description="省份(region_path第一个)", examples=["110000"])
    is_domestic :bool=Field(True, description="是否是国内项目")
    company_id: str = Field("", description="所属公司ID", examples=["company123"])
    company_name: str = Field("", description="所属公司名称", examples=["国电投江苏公司"])
    syxs: Optional[str] = Field(None, description="升压站型式")
    sub_type: Optional[str] = Field(None, description="光伏类别")
    scgc_type: Optional[str] = Field(None, description="送出工程建设方式")

    # 基础信息-允许更改
    address: str = Field("", description="项目地址", examples=["某省某市某区"])
    code: str = Field("", description="项目编码", examples=["XM2025001"])
    name: str = Field(..., description="项目名称", examples=["XX新能源项目"])
    short_name: str = Field("", description="项目简称", examples=["XX项目"])
    manager_name: str = Field("", description="负责人姓名", examples=["张三"])
    manager_phone: str = Field("", description="负责人电话", examples=["13800000000"])
    

    # 容量信息
    authorization_date: Optional[DateStr] = Field(None, description="核准日期", examples=["2024-01-01"])
    authorized_capacity: float = Field(0.0, description="核准容量（万千瓦）", examples=[10.0])
    # 投决
    investment_decision_capacity: Optional[float] = Field(None, description="投资决策容量", examples=[8.0])
    investment_decision_date: Optional[DateStr] = Field(None, description="投资决策日期", examples=["2024-02-01"])
    # 开工
    plan_construction_capacity: float = Field(0.0, description="本年度计划开工容量", examples=[5.0])
    plan_construction_date: Optional[DateStr] = Field(None, description="本年度计划开工日期", examples=["2024-03-01"])
    actual_construction_capacity: float = Field(0.0, description="本年度实际开工容量", examples=[4.0])
    actual_construction_date: Optional[DateStr] = Field(None, description="本年度实际开工日期", examples=["2024-04-01"])
    accumulated_construction_capacity: float = Field(0.0, description="累计开工容量", examples=[12.0])
    constructing_capacity: float = Field(0.0, description="在建容量", examples=[6.0])
    
    # 投产
    ensure_production_capacity: float = Field(0.0, description="本年度确保投产容量", examples=[3.0])
    challenge_production_capacity: float = Field(0.0, description="本年度揭榜投产容量", examples=[2.0])
    climb_production_capacity: float = Field(0.0, description="本年度登高投产容量", examples=[1.0])
    plan_production_date: Optional[DateStr] = Field(None, description="计划投产日期", examples=["2024-08-01"])
    plan_full_production_date: Optional[DateStr] = Field(None, description="计划全部投产日期", examples=["2024-09-01"])
    actual_production_date: Optional[DateStr] = Field(None, description="实际投产日期", examples=["2024-08-15"])
    actual_full_production_date: Optional[DateStr] = Field(None, description="实际全投日期", examples=["2024-09-10"])
    production_capacity: Optional[float] = Field(0.0, description="本年度投产容量", examples=[2.0])
    production_date: Optional[DateStr] = Field(None, description="本年度首批投产日期", examples=["2024-09-01"])
    total_production_capacity: Optional[float] = Field(0.0, description="全部投产容量", examples=[2.0])

    # 投资
    dynamic_investment: float = Field(0.0, description="动态总投资", examples=[100000.0])
    complete_investment: float = Field(0.0, description="完成投资", examples=[80000.0])

    # 其他信息
    progress_type: ProgressType | None = Field(None, description="推进分类", examples=[ProgressType.A])
    key_constraints: KeyConstraints = Field(KeyConstraints.NONE, description="关键制约", examples=[KeyConstraints.NONE])
    key_constraints_remark: Optional[str] = Field("", description="关键制约备注", examples=["无"])
    status: Optional[str] = Field(None, description="项目状态")
    apply_file_ids: List[str] = Field(default_factory=list, description="申请表附件ID列表", examples=[[]])
    
    # 拓展信息
    dbtc_score_list: Optional[list] = Field(default_factory=list, description='达标投产评分列表') # 这里项目用的是list而不是List
    approval_status: Optional[str] = Field(None, description="审核状态", examples=["pending"])



class ProjectResponseBaseList(BaseModel):
    page: int
    page_size: int
    total: int
    list: List[ProjectResponseBase] = []




# ==================== Update ====================

class KeyConstraintsRemarkMixin:
    """关键制约备注校验混入类"""

    @field_validator("key_constraints_remark")
    def validate_key_constraints_remark(cls, v):
        if v is None:
            return v
        if len(v) > 500:
            raise HTTPException(detail="关键制约备注不能超过500个字符", status_code=400)
        return v

class AuthorizationDateMixin:
    """关键制约备注校验混入类"""

    @field_validator("authorization_date")
    def validate_actual_date(cls, v):
        if v is None:
            return v
        if v > get_current_date():
            raise HTTPException(detail='核准/备案日期不能大于今天', status_code=400)
        return v

class ProjectBaseInfoUpdate(BaseModel, KeyConstraintsRemarkMixin, AuthorizationDateMixin):
    """
    项目基本信息 PROJECT_BASE_INFO
    """
    # 基础信息-允许更改
    id: str = Field(..., description="项目id", examples=["uuid"])
    address: str | None = Field(None, description="项目地址", examples=["某省某市某区"])
    code: str | None = Field(None, description="项目编码", examples=["XM2025001"])
    name: str = Field(..., description="项目名称", examples=["XX新能源项目"])
    short_name: str | None = Field(None, description="项目简称", examples=["XX项目"])
    manager_name: str | None = Field(None, description="负责人姓名", examples=["张三"])
    manager_phone: str | None = Field(None, description="负责人电话", examples=["13800000000"])
    # 其他信息
    progress_type: ProgressType = Field(..., description="推进分类", examples=[ProgressType.A])
    key_constraints: KeyConstraints | None = Field(None, description="关键制约", examples=[KeyConstraints.NONE])
    key_constraints_remark: str | None = Field(None, description="关键制约备注", examples=["无"])
    apply_file_ids: List[str] | None = Field(None, description="申请表附件ID列表", examples=[[]])
    # 拓展信息
    dbtc_score_list: list[DBTCSCORE] | None = Field(None, description='达标投产评分列表') # 这里项目用的是list而不是List

    # 核准
    authorization_date: DateStr | None = Field(None, description="核准日期", examples=["2024-01-01"])
    authorized_capacity: float | None = Field(None, description="核准容量（万千瓦）", examples=[10.0])



class _ProductionPlanNode(BaseModel):
    year: int = Field(..., description="计划年份", examples=[2024])
    capacity: float = Field(..., description="确保投产容量", examples=[3.0])

class ProjectEnsureCapacity(BaseModel):
    """
    PROJECT_ENSURE_CAPACITY
    填写项目确保投产容量列表，系统根据列表自动计算ensure_production_capacity字段
    """
    # 确保投产容量
    ensure_production_capacity_list : list[_ProductionPlanNode] = Field(..., description="确保投产容量列表（每次必须填写全部）")

class ProjectClimbCapacity(BaseModel):
    """
    PROJECT_CLIMB_CAPACITY
    填写项目登高投产容量列表，系统根据列表自动计算climb_production_capacity字段
    """
    # 登高投产容量
    climb_production_capacity_list : list[_ProductionPlanNode] = Field(..., description="登高投产容量列表（每次必须填写全部）")
class ProjectChallengeCapacity(BaseModel):
    """
    PROJECT_CHALLENGE_CAPACITY
    填写项目揭榜投产容量列表，系统根据列表自动计算challenge_production_capacity字段
    """
    # 揭榜投产容量
    challenge_production_capacity_list : list[_ProductionPlanNode] = Field(..., description="揭榜投产容量列表（每次必须填写全部）")



class _ActualNodeData(BaseModel):
    capacity: float = Field(..., description="实际节点容量", examples=[4.0])
    date: DateStr = Field(..., description="实际节点日期", examples=["2024-04-01"])
class ProjectActualConstruction(BaseModel):
    """
    PROJECT_ACTUAL_CONSTRUCTION
    项目实际开工节点
    
    系统根据实际开工节点自动计算以下字段：
    actual_construction_capacity 本年度实际开工容量
    actual_construction_date 本年度实际开工日期
    accumulated_construction_capacity 累计开工容量
    constructing_capacity 在建容量
    """
    actual_construction_list : list[_ActualNodeData] | None = Field(None, description="实际开工节点列表（每次必须填写全部）")

class _PlanNodeData(BaseModel):
    capacity: float = Field(..., description="计划节点容量", examples=[5.0])
    date: DateStr = Field(..., description="本年度计日期", examples=["2024-03-01"])

    @field_validator("capacity")
    def validate_capacity(cls, v: float) -> float:
        if v < 0:
            raise HTTPException(status_code=400, detail="节点容量必须大于等于0")
        return v

class ProjectPlanConstruction(BaseModel):
    """
    PROJECT_PLAN_CONSTRUCTION
    项目计划开工节点
    
    系统根据计划开工节点自动计算：
    plan_construction_capacity 本年度计划开工容量
    plan_construction_date 本年度计划开工日期
    """
    plan_construction_list : list[_PlanNodeData] | None = Field(None, description="计划开工节点列表（每次必须填写全部）")

class ProjectInvestmentDecision(BaseModel):
    """
    PROJECT_INVESTMENT_DECISION
    投资决策容量和日期
    """
    investment_decision_capacity: float = Field(..., description="投资决策容量", examples=[8.0])
    investment_decision_date: DateStr = Field(..., description="投资决策日期", examples=["2024-02-01"])

    @field_validator("investment_decision_date")
    def validate_investment_decision_date(cls, v):
        if v is None:
            return v
        if v > get_current_date():
            raise HTTPException(detail='投资决策日期不能大于今天', status_code=400)
        return v
    @field_validator("investment_decision_capacity")
    def validate_investment_decision_capacity(cls, v: float) -> float:
        if v < 0:
            raise HTTPException(status_code=400, detail="投资决策容量必须大于等于0")
        return v

class ProjectKeyConstraints(BaseModel, KeyConstraintsRemarkMixin):
    """
    PROJECT_KEY_CONSTRAINTS
    关键制约
    """
    key_constraints: KeyConstraints | None = Field(None, description="关键制约", examples=[KeyConstraints.NONE])
    key_constraints_remark: str | None = Field(None, description="关键制约备注", examples=["无"])

class _ActualProductionNode(BaseModel):
    capacity: float = Field(..., description="实际投产容量", examples=[2.0])
    date: DateStr = Field(..., description="实际投产日期", examples=["2024-08-15"])

    @field_validator("capacity")
    def validate_capacity(cls, v: float) -> float:
        if v < 0:
            raise HTTPException(status_code=400, detail="实际投产容量必须大于等于0")
        return v

    @field_validator("date")
    def validate_date(cls, v):
        if v is None:
            return v
        if v > get_current_date():
            raise HTTPException(detail='实际投产日期不能大于今天', status_code=400)
        return v

class ProjectProductionCapacity(BaseModel):
    """
    PROJECT_PRODUCTION_CAPACITY
    填写项目投产数据
    每个项目在各年份或一年内可能有多次实际投产
    系统会根据投产节点列表数据，自动计算
    production_capacity 本年度投产容量
    production_date 本年度首批投产日期
    total_production_capacity 全部投产容量
    """
    plan_production_date: DateStr | None = Field(None, description="集团公司计划投产日期", examples=["2024-08-01"])
    plan_full_production_date: DateStr | None = Field(None, description="集团公司计划全部投产日期", examples=["2024-09-01"])
    ic_plan_first_production_date: DateStr | None = Field(None, description="区域公司计划首批投产日期(只有新能源需要)",examples=["2024-08-01"])
    ic_plan_full_production_date: DateStr | None = Field(None, description="区域公司计划全投日期(只有新能源需要)",examples=["2024-09-01"])
    actual_production_date: DateStr | None = Field(None, description="实际投产日期(只有新能源需要)", examples=["2024-08-15"])
    actual_full_production_date: DateStr | None = Field(None, description="实际全投日期(只有新能源需要)", examples=["2024-09-10"])
    actual_production_list : list[_ActualProductionNode] | None = Field(None, description="实际投产节点列表(每次必须填写全部)(只有新能源需要)")
    @field_validator("actual_production_date")
    def validate_actual_production_date(cls, v):
        if v is None:
            return v
        if v > get_current_date():
            raise HTTPException(detail='实际投产日期不能大于今天', status_code=400)
        return v

    @field_validator("actual_full_production_date")
    def validate_actual_full_production_date(cls, v):
        if v is None:
            return v
        if v > get_current_date():
            raise HTTPException(detail='实际全投日期不能大于今天', status_code=400)
        return v

class ProjectCompleteInvestment(BaseModel):
    """
    PROJECT_COMPLETE_INVESTMENT
    完成投资投资
    """

    complete_investment: float = Field(..., description="完成投资", examples=[80000.0])

    @field_validator("complete_investment")
    def validate_complete_investment(cls, v: float) -> float:
        if v < 0:
            raise HTTPException(status_code=400,detail="完成投资必须大于等于0")
        return v

class ProjectSettlementInvestment(BaseModel):
    """
    PROJECT_SETTLEMENT_INVESTMENT
    合同结算投资情况
    只有抽蓄-水电-煤电-气电项目类型可操作
    """

    implementation_estimate: float = Field(..., description="执行概算", examples=[80000.0])
    static_total_investment: float = Field(..., description="静态总投资", examples=[80000.0])
    completed_investment: float = Field(..., description="完成投资", examples=[80000.0])
    dynamic_investment: float = Field(..., description="动态总投资", examples=[80000.0])

    @field_validator("implementation_estimate")
    def validate_implementation_estimate(cls, v: float) -> float:
        if v < 0:
            raise HTTPException(status_code=400,detail="执行概算必须大于等于0")
        return v

    @field_validator("static_total_investment")
    def validate_static_total_investment(cls, v: float) -> float:
        if v < 0:
            raise HTTPException(status_code=400, detail="静态总投资必须大于等于0")
        return v

    @field_validator("completed_investment")
    def validate_completed_investment(cls, v: float) -> float:
        if v < 0:
            raise HTTPException(status_code=400, detail="完成投资必须大于等于0")
        return v

    @field_validator("dynamic_investment")
    def validate_dynamic_investment(cls, v: float) -> float:
        if v < 0:
            raise HTTPException(status_code=400, detail="动态总投资必须大于等于0")
        return v

class ProjectDynamicInvestment(BaseModel):
    """
    PROJECT_DYNAMIC_INVESTMENT
    """
    # 动态总投资
    dynamic_investment: float | None = Field(None, description="动态总投资", examples=[100000.0])

    @field_validator("dynamic_investment")
    def validate_dynamic_investment(cls, v: float) -> float:
        if v < 0:
            raise HTTPException(status_code=400, detail="动态总投资必须大于等于0")
        return v

# ======================= 水电抽蓄专用 =============================


# ==================== 枚举说明 用于文档自动生成 ====================

