from typing import Literal, Optional

from pydantic import BaseModel, ConfigDict, Field


class AttributeInfo(BaseModel):
    """음악 속성 정보"""

    genre: str = Field(..., description="음악 장르")
    vocal: str = Field(..., description="보컬 스타일")
    tempo: str = Field(..., description="템포")
    mood: str = Field(..., description="분위기")


class GenerateRequestImg(BaseModel):
    """이미지 URL 스키마"""

    url: str = Field(..., description="이미지 URL")
    name: Optional[str] = Field(None, description="이미지명 (없으면 URL에서 추출)")


class GenerateRequestInfo(BaseModel):
    """생성 요청 정보 스키마 (이미지 제외)"""

    customer_name: str = Field(..., description="고객명/가게명")
    region: str = Field(..., description="지역명")
    detail_region_info: Optional[str] = Field(None, description="상세 지역 정보")
    attribute: AttributeInfo = Field(..., description="음악 속성 정보")
    language: str = Field(
        default="Korean",
        description="가사 출력 언어 (Korean, English, Chinese, Japanese, Thai, Vietnamese)",
    )


class GenerateRequest(GenerateRequestInfo):
    """기본 생성 요청 스키마 (이미지 없음, JSON body)

    이미지 없이 프로젝트 정보만 전달합니다.
    """

    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "customer_name": "스테이 머뭄",
                "region": "군산",
                "detail_region_info": "군산 신흥동 말랭이 마을",
                "attribute": {
                    "genre": "K-Pop",
                    "vocal": "Raspy",
                    "tempo": "110 BPM",
                    "mood": "happy",
                },
                "language": "Korean",
            }
        }
    )


class GenerateUrlsRequest(GenerateRequestInfo):
    """URL 기반 생성 요청 스키마 (JSON body)

    GenerateRequestInfo를 상속받아 이미지 목록을 추가합니다.
    """

    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "customer_name": "스테이 머뭄",
                "region": "군산",
                "detail_region_info": "군산 신흥동 말랭이 마을",
                "attribute": {
                    "genre": "K-Pop",
                    "vocal": "Raspy",
                    "tempo": "110 BPM",
                    "mood": "happy",
                },
                "language": "Korean",
                "images": [
                    {"url": "https://example.com/images/image_001.jpg"},
                    {"url": "https://example.com/images/image_002.jpg", "name": "외관"},
                ],
            }
        }
    )

    images: list[GenerateRequestImg] = Field(
        ..., description="이미지 URL 목록", min_length=1
    )


class GenerateUploadResponse(BaseModel):
    """파일 업로드 기반 생성 응답 스키마"""

    task_id: str = Field(..., description="작업 고유 식별자 (UUID7)")
    status: Literal["processing", "completed", "failed"] = Field(
        ..., description="작업 상태"
    )
    message: str = Field(..., description="응답 메시지")
    uploaded_count: int = Field(..., description="업로드된 이미지 개수")


class GenerateResponse(BaseModel):
    """생성 응답 스키마"""

    task_id: str = Field(..., description="작업 고유 식별자 (UUID7)")
    status: Literal["processing", "completed", "failed"] = Field(
        ..., description="작업 상태"
    )
    message: str = Field(..., description="응답 메시지")


class CrawlingRequest(BaseModel):
    """크롤링 요청 스키마"""

    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "url": "https://map.naver.com/p/search/%EC%8A%A4%ED%85%8C%EC%9D%B4%EB%A8%B8%EB%AD%84/place/1133638931?c=14.70,0,0,0,dh&placePath=/photo?businessCategory=pension&fromPanelNum=2&locale=ko&searchText=%EC%8A%A4%ED%85%8C%EC%9D%B4%EB%A8%B8%EB%AD%84&svcName=map_pcv5&timestamp=202512191123&fromPanelNum=2&locale=ko&searchText=%EC%8A%A4%ED%85%8C%EC%9D%B4%EB%A8%B8%EB%AD%84&svcName=map_pcv5&timestamp=202512191007&from=map&entry=bmp&filterType=%EC%97%85%EC%B2%B4&businessCategory=pension"
            }
        }
    )

    url: str = Field(..., description="네이버 지도 장소 URL")


class ProcessedInfo(BaseModel):
    """가공된 장소 정보 스키마"""

    customer_name: str = Field(..., description="고객명/가게명 (base_info.name)")
    region: str = Field(..., description="지역명 (roadAddress에서 추출한 시 이름)")
    detail_region_info: str = Field(..., description="상세 지역 정보 (roadAddress)")


class MarketingAnalysis(BaseModel):
    """마케팅 분석 결과 스키마"""

    report: str = Field(..., description="마케팅 분석 리포트")
    tags: list[str] = Field(default_factory=list, description="추천 태그 목록")
    facilities: list[str] = Field(default_factory=list, description="추천 부대시설 목록")


class CrawlingResponse(BaseModel):
    """크롤링 응답 스키마"""

    image_list: Optional[list[str]] = Field(None, description="이미지 URL 목록")
    image_count: int = Field(..., description="이미지 개수")
    processed_info: Optional[ProcessedInfo] = Field(
        None, description="가공된 장소 정보 (customer_name, region, detail_region_info)"
    )
    marketing_analysis: Optional[MarketingAnalysis] = Field(
        None, description="마케팅 분석 결과 (report, tags, facilities)"
    )


class ErrorResponse(BaseModel):
    """에러 응답 스키마"""

    success: bool = Field(default=False, description="요청 성공 여부")
    error_code: str = Field(..., description="에러 코드")
    message: str = Field(..., description="에러 메시지")
    detail: Optional[str] = Field(None, description="상세 에러 정보")


# =============================================================================
# Image Upload Schemas
# =============================================================================


class ImageUrlItem(BaseModel):
    """이미지 URL 아이템 스키마"""

    url: str = Field(..., description="외부 이미지 URL")
    name: Optional[str] = Field(None, description="이미지명 (없으면 URL에서 추출)")


class ImageUploadRequest(BaseModel):
    """이미지 업로드 요청 스키마 (JSON body 부분)

    URL 이미지 목록을 전달합니다.
    바이너리 파일은 multipart/form-data로 별도 전달됩니다.
    """

    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "images": [
                    {"url": "https://example.com/images/image_001.jpg"},
                    {"url": "https://example.com/images/image_002.jpg", "name": "외관"},
                ]
            }
        }
    )

    images: Optional[list[ImageUrlItem]] = Field(
        None, description="외부 이미지 URL 목록"
    )


class ImageUploadResultItem(BaseModel):
    """업로드된 이미지 결과 아이템"""

    id: int = Field(..., description="이미지 ID")
    img_name: str = Field(..., description="이미지명")
    img_url: str = Field(..., description="이미지 URL")
    img_order: int = Field(..., description="이미지 순서")
    source: Literal["url", "file", "blob"] = Field(
        ..., description="이미지 소스 (url: 외부 URL, file: 로컬 서버, blob: Azure Blob)"
    )


class ImageUploadResponse(BaseModel):
    """이미지 업로드 응답 스키마"""

    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "task_id": "0694b716-dbff-7219-8000-d08cb5fce431",
                "total_count": 3,
                "url_count": 2,
                "file_count": 1,
                "saved_count": 3,
                "images": [
                    {
                        "id": 1,
                        "img_name": "외관",
                        "img_url": "https://example.com/images/image_001.jpg",
                        "img_order": 0,
                        "source": "url",
                    },
                    {
                        "id": 2,
                        "img_name": "내부",
                        "img_url": "https://example.com/images/image_002.jpg",
                        "img_order": 1,
                        "source": "url",
                    },
                    {
                        "id": 3,
                        "img_name": "uploaded_image.jpg",
                        "img_url": "/media/image/2024-01-15/0694b716-dbff-7219-8000-d08cb5fce431/uploaded_image_002.jpg",
                        "img_order": 2,
                        "source": "file",
                    },
                ],
                "image_urls": [
                    "https://example.com/images/image_001.jpg",
                    "https://example.com/images/image_002.jpg",
                    "/media/image/2024-01-15/0694b716-dbff-7219-8000-d08cb5fce431/uploaded_image_002.jpg",
                ],
            }
        }
    )

    task_id: str = Field(..., description="작업 고유 식별자 (새로 생성된 UUID7)")
    total_count: int = Field(..., description="총 업로드된 이미지 개수")
    url_count: int = Field(..., description="URL로 등록된 이미지 개수")
    file_count: int = Field(..., description="파일로 업로드된 이미지 개수")
    saved_count: int = Field(..., description="Image 테이블에 저장된 row 수")
    images: list[ImageUploadResultItem] = Field(..., description="업로드된 이미지 목록")
    image_urls: list[str] = Field(..., description="Image 테이블에 저장된 현재 task_id의 이미지 URL 목록")
