import json
import uuid
from datetime import datetime
from enum import Enum
from typing import Optional

from pydantic import BaseModel, Field, validator, ConfigDict
from pydantic.alias_generators import to_camel

from app.db.models.data_collection import CollectionTask, TaskExecution, CollectionTemplate
from app.module.shared.schema import TaskStatus


class SyncMode(str, Enum):
    ONCE = "ONCE"
    SCHEDULED = "SCHEDULED"

class CollectionConfig(BaseModel):
    parameter: Optional[dict] = Field(None, description="模板参数")
    reader: Optional[dict] = Field(None, description="reader参数")
    writer: Optional[dict] = Field(None, description="writer参数")
    job: Optional[dict] = Field(None, description="任务配置")

class CollectionTaskBase(BaseModel):
    id: str = Field(..., description="任务id")
    name: str = Field(..., description="任务名称")
    description: Optional[str] = Field(None, description="任务描述")
    target_path: str = Field(..., description="目标存放路径")
    config: CollectionConfig = Field(..., description="任务配置")
    template_id: str = Field(..., description="模板ID")
    template_name: Optional[str] = Field(None, description="模板名称")
    status: TaskStatus = Field(..., description="任务状态")
    sync_mode: SyncMode = Field(default=SyncMode.ONCE, description="同步方式")
    schedule_expression: Optional[str] = Field(None, description="调度表达式（cron）")
    retry_count: int = Field(default=3, description="重试次数")
    timeout_seconds: int = Field(default=3600, description="超时时间")
    last_execution_id: Optional[str] = Field(None, description="最后执行id")
    created_at: Optional[datetime] = Field(None, description="创建时间")
    updated_at: Optional[datetime] = Field(None, description="更新时间")
    created_by: Optional[str] = Field(None, description="创建人")
    updated_by: Optional[str] = Field(None, description="更新人")

    model_config = ConfigDict(
        alias_generator=to_camel,
        populate_by_name=True
    )

class CollectionTaskCreate(BaseModel):
    name: str = Field(..., description="任务名称")
    description: Optional[str] = Field(None, description="任务描述")
    sync_mode: SyncMode = Field(default=SyncMode.ONCE, description="同步方式")
    schedule_expression: Optional[str] = Field(None, description="调度表达式（cron）")
    config: CollectionConfig = Field(..., description="任务配置")
    template_id: str = Field(..., description="模板ID")

    model_config = ConfigDict(
        alias_generator=to_camel,
        populate_by_name=True
    )

def converter_to_response(task: CollectionTask) -> CollectionTaskBase:
    return CollectionTaskBase(
        id=task.id,
        name=task.name,
        description=task.description,
        sync_mode=task.sync_mode,
        template_id=task.template_id,
        template_name=task.template_name,
        target_path=task.target_path,
        config=json.loads(task.config),
        schedule_expression=task.schedule_expression,
        status=task.status,
        retry_count=task.retry_count,
        timeout_seconds=task.timeout_seconds,
        last_execution_id=task.last_execution_id,
        created_at=task.created_at,
        updated_at=task.updated_at,
        created_by=task.created_by,
        updated_by=task.updated_by,
    )

def convert_for_create(task: CollectionTaskCreate, task_id: str) -> CollectionTask:
    return CollectionTask(
        id=task_id,
        name=task.name,
        description=task.description,
        sync_mode=task.sync_mode,
        template_id=task.template_id,
        target_path=f"/dataset/local/{task_id}",
        config=json.dumps(task.config.dict()),
        schedule_expression=task.schedule_expression,
        status=TaskStatus.PENDING.name
    )

def create_execute_record(task: CollectionTask) -> TaskExecution:
    execution_id = str(uuid.uuid4())
    return TaskExecution(
        id=execution_id,
        task_id=task.id,
        task_name=task.name,
        status=TaskStatus.RUNNING.name,
        started_at=datetime.now(),
        log_path=f"/flow/data-collection/{task.id}/{execution_id}.log"
    )


class TaskExecutionBase(BaseModel):
    id: str = Field(..., description="执行记录ID")
    task_id: str = Field(..., description="任务ID")
    task_name: str = Field(..., description="任务名称")
    status: Optional[str] = Field(None, description="执行状态")
    log_path: Optional[str] = Field(None, description="日志文件路径")
    started_at: Optional[datetime] = Field(None, description="开始时间")
    completed_at: Optional[datetime] = Field(None, description="完成时间")
    duration_seconds: Optional[int] = Field(None, description="执行时长（秒）")
    error_message: Optional[str] = Field(None, description="错误信息")
    created_at: Optional[datetime] = Field(None, description="创建时间")
    updated_at: Optional[datetime] = Field(None, description="更新时间")
    created_by: Optional[str] = Field(None, description="创建者")
    updated_by: Optional[str] = Field(None, description="更新者")

    model_config = ConfigDict(
        alias_generator=to_camel,
        populate_by_name=True
    )


def converter_execution_to_response(execution: TaskExecution) -> TaskExecutionBase:
    return TaskExecutionBase(
        id=execution.id,
        task_id=execution.task_id,
        task_name=execution.task_name,
        status=execution.status,
        log_path=execution.log_path,
        started_at=execution.started_at,
        completed_at=execution.completed_at,
        duration_seconds=execution.duration_seconds,
        error_message=execution.error_message,
        created_at=execution.created_at,
        updated_at=execution.updated_at,
        created_by=execution.created_by,
        updated_by=execution.updated_by,
    )


class CollectionTemplateBase(BaseModel):
    id: str = Field(..., description="模板ID")
    name: str = Field(..., description="模板名称")
    description: Optional[str] = Field(None, description="模板描述")
    source_type: str = Field(..., description="源数据源类型")
    source_name: str = Field(..., description="源数据源名称")
    target_type: str = Field(..., description="目标数据源类型")
    target_name: str = Field(..., description="目标数据源名称")
    template_content: dict = Field(..., description="模板内容")
    built_in: Optional[bool] = Field(None, description="是否系统内置模板")
    created_at: Optional[datetime] = Field(None, description="创建时间")
    updated_at: Optional[datetime] = Field(None, description="更新时间")
    created_by: Optional[str] = Field(None, description="创建者")
    updated_by: Optional[str] = Field(None, description="更新者")

    model_config = ConfigDict(
        alias_generator=to_camel,
        populate_by_name=True
    )


def converter_template_to_response(template: CollectionTemplate) -> CollectionTemplateBase:
    return CollectionTemplateBase(
        id=template.id,
        name=template.name,
        description=template.description,
        source_type=template.source_type,
        source_name=template.source_name,
        target_type=template.target_type,
        target_name=template.target_name,
        template_content=template.template_content,
        built_in=template.built_in,
        created_at=template.created_at,
        updated_at=template.updated_at,
        created_by=template.created_by,
        updated_by=template.updated_by,
    )
