"""UUID 字段长度单元测试 — 验证标准 UUID（带横杠，36字符）可正常插入.

覆盖：
  - 所有从 varchar(32) 扩到 varchar(36) 的表
  - 插入标准 UUID 格式（带横杠）不报 StringDataRightTruncation
  - 字段长度从 32 扩到 36 后 ORM 模型定义正确
"""

from __future__ import annotations

import uuid

import pytest

from packages.adapters.sqlalchemy_impl.models import (
    ClassificationJobModel,
    EditPlanClipModel,
    EditPlanModel,
    EditTemplateModel,
    GeneratedVideoModel,
    GenerationTaskModel,
    IngestJobModel,
    JobModel,
    ProjectModel,
    TemplateClipConfigModel,
)


def _uuid() -> str:
    """生成标准 UUID 字符串（带横杠，36 字符）."""
    return str(uuid.uuid4())


class TestUUIDFieldLengthModels:
    """验证 ORM 模型中 UUID 字段定义为 String(36)."""

    def _get_column_type_length(self, model_cls, column_name: str) -> int:
        """获取模型列的 String 长度."""
        col = model_cls.__table__.columns[column_name]
        return col.type.length

    # ── ProjectModel ──────────────────────────────────────────────────────────

    def test_project_id_is_36(self):
        assert self._get_column_type_length(ProjectModel, "id") == 36

    def test_project_owner_user_id_is_36(self):
        assert self._get_column_type_length(ProjectModel, "owner_user_id") == 36

    # ── EditTemplateModel ─────────────────────────────────────────────────────

    def test_edit_template_id_is_36(self):
        assert self._get_column_type_length(EditTemplateModel, "id") == 36

    # ── EditPlanModel ─────────────────────────────────────────────────────────

    @pytest.mark.parametrize(
        "col",
        ["id", "template_id", "source_edit_plan_id", "project_id", "created_by_user_id"],
    )
    def test_edit_plan_uuid_fields_are_36(self, col):
        assert self._get_column_type_length(EditPlanModel, col) == 36

    # ── TemplateClipConfigModel ───────────────────────────────────────────────

    @pytest.mark.parametrize("col", ["id", "template_id"])
    def test_template_clip_config_uuid_fields_are_36(self, col):
        assert self._get_column_type_length(TemplateClipConfigModel, col) == 36

    # ── EditPlanClipModel ─────────────────────────────────────────────────────

    @pytest.mark.parametrize(
        "col",
        ["id", "plan_id", "template_clip_config_id", "asset_id"],
    )
    def test_edit_plan_clip_uuid_fields_are_36(self, col):
        assert self._get_column_type_length(EditPlanClipModel, col) == 36

    # ── IngestJobModel（P0 bug 所在表）─────────────────────────────────────────

    @pytest.mark.parametrize(
        "col",
        ["id", "project_id", "library_id", "result_asset_id"],
    )
    def test_ingest_job_uuid_fields_are_36(self, col):
        assert self._get_column_type_length(IngestJobModel, col) == 36

    def test_ingest_job_library_id_accepts_standard_uuid(self):
        """P0 回归：library_id 必须能容纳标准 UUID（36 字符带横杠）."""
        standard_uuid = "550e8400-e29b-41d4-a716-446655440000"
        assert len(standard_uuid) == 36
        col = IngestJobModel.__table__.columns["library_id"]
        assert col.type.length >= 36

    # ── ClassificationJobModel ────────────────────────────────────────────────

    @pytest.mark.parametrize("col", ["id", "project_id", "asset_id"])
    def test_classification_job_uuid_fields_are_36(self, col):
        assert self._get_column_type_length(ClassificationJobModel, col) == 36

    # ── GenerationTaskModel ───────────────────────────────────────────────────

    @pytest.mark.parametrize(
        "col",
        [
            "id",
            "project_id",
            "strategy_id",
            "asset_library_id",
            "voice_library_id",
            "created_by_user_id",
            "source_edit_plan_id",
            "batch_id",
        ],
    )
    def test_generation_task_uuid_fields_are_36(self, col):
        assert self._get_column_type_length(GenerationTaskModel, col) == 36

    # ── GeneratedVideoModel ───────────────────────────────────────────────────

    @pytest.mark.parametrize(
        "col",
        ["id", "project_id", "generation_task_id", "duplicate_of"],
    )
    def test_generated_video_uuid_fields_are_36(self, col):
        assert self._get_column_type_length(GeneratedVideoModel, col) == 36

    # ── JobModel ──────────────────────────────────────────────────────────────

    @pytest.mark.parametrize(
        "col",
        ["id", "project_id", "source_id", "created_by_user_id"],
    )
    def test_job_uuid_fields_are_36(self, col):
        assert self._get_column_type_length(JobModel, col) == 36


class TestUUIDInsertWithHyphens:
    """验证标准 UUID（带横杠）可构造 ORM 对象，字段长度足够."""

    def test_ingest_job_model_construct_with_standard_uuid(self):
        """P0 回归测试：用标准 UUID 构造 IngestJobModel 不报错."""
        std_uuid = _uuid()
        assert len(std_uuid) == 36

        job = IngestJobModel(
            id=_uuid(),
            project_id=_uuid(),
            library_id=std_uuid,  # ← 关键：标准 UUID 带横杠
            storage_key="test/file.mp4",
            result_asset_id=_uuid(),
        )
        assert job.library_id == std_uuid
        assert len(job.library_id) == 36

    def test_project_model_construct_with_standard_uuid(self):
        project = ProjectModel(
            id=_uuid(),
            owner_user_id=_uuid(),
            name="test",
        )
        assert len(project.id) == 36
        assert len(project.owner_user_id) == 36

    def test_generation_task_model_construct_with_standard_uuid(self):
        task = GenerationTaskModel(
            id=_uuid(),
            project_id=_uuid(),
            asset_library_id=_uuid(),
            created_by_user_id=_uuid(),
            source_edit_plan_id=_uuid(),
            batch_id=_uuid(),
        )
        assert len(task.id) == 36
        assert len(task.asset_library_id) == 36

    def test_edit_plan_model_construct_with_standard_uuid(self):
        plan = EditPlanModel(
            id=_uuid(),
            template_id=_uuid(),
            source_edit_plan_id=_uuid(),
            project_id=_uuid(),
            created_by_user_id=_uuid(),
        )
        assert len(plan.id) == 36
        assert len(plan.template_id) == 36

    def test_generated_video_model_construct_with_standard_uuid(self):
        video = GeneratedVideoModel(
            id=_uuid(),
            project_id=_uuid(),
            generation_task_id=_uuid(),
            duplicate_of=_uuid(),
            name="test.mp4",
            file_url="https://example.com/test.mp4",
            file_size=1000,
            duration=10.0,
            width=1280,
            height=720,
            fps=25.0,
        )
        assert len(video.id) == 36
        assert len(video.duplicate_of) == 36
