from datetime import datetime
from pydantic import BaseModel, ConfigDict, Field, field_validator
from fastapi import File, Form, UploadFile
from typing import Optional, List
from uuid import UUID
from .base import BaseResponse

class RequestOTPPayload(BaseModel):
    nomor_pelanggan: str

class PelangganCreate(BaseModel):
    nama_pelanggan: str
    nomor_pelanggan: str
    latitude_rumah: float
    longitude_rumah: float
    otp_code: str
    keterangan: Optional[str] = None

    @classmethod
    def as_form(
        cls,
        nama_pelanggan: str = Form(...),
        nomor_pelanggan: str = Form(...),
        latitude_rumah: float = Form(...),
        longitude_rumah: float = Form(...),
        otp_code: str = Form(...),
        keterangan: Optional[str] = Form(None),
    ):
        return cls(
            nama_pelanggan=nama_pelanggan,
            nomor_pelanggan=nomor_pelanggan,
            latitude_rumah=latitude_rumah,
            longitude_rumah=longitude_rumah,
            otp_code=otp_code,
            keterangan=keterangan,
        )


class PelangganResponseData(BaseModel):
    id: UUID
    no_activity: str
    nama_pelanggan: str
    nomor_pelanggan: str
    latitude_rumah: float
    longitude_rumah: float
    keterangan: Optional[str] = None
    kode_sales: str
    status: str
    tanggal: datetime

    model_config = ConfigDict(
        from_attributes=True
    )
class PelangganResponse(BaseResponse[PelangganResponseData]):
    model_config = ConfigDict(
        from_attributes=True
    )
class PelangganListResponse(BaseResponse[List[PelangganResponseData]]):
    model_config = ConfigDict(
        from_attributes=True
    )
class CheckinFtthCreate(BaseModel):
    no_activity: str
    fat_code: str
    foto_fat: UploadFile
    status_pemesanan: str
    latitude_sales: float
    longitude_sales: float

    @classmethod
    def as_form(
        cls,
        no_activity: str = Form(...),
        fat_code: str = Form(...),
        foto_fat: UploadFile = File(...),
        status_pemesanan: str = Form(...),
        latitude_sales: float = Form(...),
        longitude_sales: float = Form(...),
    ):
        return cls(
            no_activity=no_activity,
            fat_code=fat_code,
            foto_fat=foto_fat,
            status_pemesanan=status_pemesanan,
            latitude_sales=latitude_sales,
            longitude_sales=longitude_sales,
        )


class CheckinFtthDetail(BaseModel):
    id: UUID
    no_activity: str
    nama_pelanggan: str
    nomor_pelanggan: str
    latitude_rumah: float
    longitude_rumah: float
    keterangan: Optional[str] = None
    fat_code: str
    foto_fat: str
    latitude_fat: float
    longitude_fat: float
    jarak_meter: float
    status_pemesanan: str
    tanggal_po: Optional[datetime] = None
    tanggal_so: Optional[datetime] = None
    tanggal_sa: Optional[datetime] = None
    tanggal_pa: Optional[datetime] = None
    kode_sales: str
    status_checkin: str
    tanggal_form1: datetime
    tanggal_checkin: datetime

    model_config = ConfigDict(
        from_attributes=True
    )
class CheckinFtthResponse(BaseResponse[CheckinFtthDetail]):
    model_config = ConfigDict(
        from_attributes=True
    )
class CheckinFtthListResponse(BaseResponse[List[CheckinFtthDetail]]):
    model_config = ConfigDict(
        from_attributes=True
    )
class HistoryItem(BaseModel):
    id: UUID
    no_activity: str
    nama_pelanggan: str
    tanggal: datetime
    form_status: str  # "pending" atau "done"
    status_pemesanan: str
    kode_sales: str

    model_config = ConfigDict(
        from_attributes=True
    )
class HistoryListResponse(BaseResponse[List[HistoryItem]]):
    model_config = ConfigDict(
        from_attributes=True
    )
class PemesananStatusItem(BaseModel):
    id: UUID
    no_activity: str
    nama_pelanggan: str
    tanggal_checkin: datetime
    status_pemesanan: str
    kode_sales: str

    model_config = ConfigDict(
        from_attributes=True
    )
class PemesananStatusListResponse(BaseResponse[List[PemesananStatusItem]]):
    model_config = ConfigDict(
        from_attributes=True
    )
class CheckinFtthUpdateStatus(BaseModel):
    status_pemesanan: str
    keterangan: Optional[str] = None

    @field_validator("status_pemesanan")
    @classmethod
    def validate_status_pemesanan(cls, v: str) -> str:
        allowed = {"PO", "SO", "SA", "PA"}
        v_upper = v.upper()
        if v_upper not in allowed:
            raise ValueError("Status pemesanan harus salah satu dari: PO, SO, SA, PA")
        return v_upper


class CheckFatVerificationRequest(BaseModel):
    latitude_sales: float
    longitude_sales: float

    @classmethod
    def as_form(
        cls,
        latitude_sales: float = Form(...),
        longitude_sales: float = Form(...),
    ):
        return cls(
            latitude_sales=latitude_sales,
            longitude_sales=longitude_sales,
        )

class CheckFatVerificationResponseData(BaseModel):
    verified: bool
    verification_method: str  # "OCR" | "PROXIMITY_FALLBACK" | "FAILED"
    detected_fat_code: Optional[str] = None
    raw_ocr_text: Optional[str] = None
    ocr_time_ms: Optional[float] = None
    distance_meters: Optional[float] = None
    total_time_ms: Optional[float] = None
    message: str

class CheckFatVerificationResponse(BaseResponse[CheckFatVerificationResponseData]):
    model_config = ConfigDict(
        from_attributes=True
    )
class SubmitNewFatRequest(BaseModel):
    no_activity: str
    latitude_fat: float
    longitude_fat: float
    tipe_fat: str
    status_pemesanan: str

    @classmethod
    def as_form(
        cls,
        no_activity: str = Form(...),
        latitude_fat: float = Form(...),
        longitude_fat: float = Form(...),
        tipe_fat: str = Form(...),
        status_pemesanan: str = Form(...),
    ):
        return cls(
            no_activity=no_activity,
            latitude_fat=latitude_fat,
            longitude_fat=longitude_fat,
            tipe_fat=tipe_fat,
            status_pemesanan=status_pemesanan,
        )

class CheckinPelangganBrief(BaseModel):
    no_activity: str
    nama_pelanggan: str
    nomor_pelanggan: str

    model_config = ConfigDict(
        from_attributes=True
    )
class FatBaruResponseData(BaseModel):
    id: UUID
    fat_code: str
    tipe_fat: str
    longitude_fat: float
    latitude_fat: float
    slot_available: int
    slot_occupied: int
    date: datetime
    status: str
    sales_code: str
    checkins: Optional[List[CheckinPelangganBrief]] = []

    model_config = ConfigDict(
        from_attributes=True
    )
class SubmitNewFatResponseData(BaseModel):
    checkin: CheckinFtthDetail
    fat_baru: FatBaruResponseData

class SubmitNewFatResponse(BaseResponse[SubmitNewFatResponseData]):
    model_config = ConfigDict(
        from_attributes=True
    )
class JoinNewFatRequest(BaseModel):
    no_activity: str
    fat_code: str
    status_pemesanan: str

    @classmethod
    def as_form(
        cls,
        no_activity: str = Form(...),
        fat_code: str = Form(...),
        status_pemesanan: str = Form(...),
    ):
        return cls(
            no_activity=no_activity,
            fat_code=fat_code,
            status_pemesanan=status_pemesanan,
        )

class UpdateFatNewRequest(BaseModel):
    latitude_fat: float
    longitude_fat: float
    tipe_fat: str

    @classmethod
    def as_form(
        cls,
        latitude_fat: float = Form(...),
        longitude_fat: float = Form(...),
        tipe_fat: str = Form(...),
    ):
        return cls(
            latitude_fat=latitude_fat,
            longitude_fat=longitude_fat,
            tipe_fat=tipe_fat,
        )

class UpdateFatJoinRequest(BaseModel):
    fat_code: str

    @classmethod
    def as_form(
        cls,
        fat_code: str = Form(...),
    ):
        return cls(
            fat_code=fat_code,
        )

class FatBaruNearbyItem(BaseModel):
    id: UUID
    fat_code: str
    slot_available: int
    slot_occupied: int
    jarak_meter: float
    status: str
    
    model_config = ConfigDict(
        from_attributes=True
    )
class FatBaruNearbyListResponse(BaseResponse[List[FatBaruNearbyItem]]):
    model_config = ConfigDict(
        from_attributes=True
    )
class FatBaruDetailResponse(BaseResponse[FatBaruResponseData]):
    model_config = ConfigDict(
        from_attributes=True
    )

class PerformanceTestResponseData(BaseModel):
    backend_total_time_ms: float
    file_read_time_ms: float
    yolo_time_ms: Optional[float] = None
    ocr_time_ms: Optional[float] = None
    spatial_validation_time_ms: Optional[float] = None
    verified: bool
    verification_method: str
    message: str

class PerformanceTestResponse(BaseResponse[PerformanceTestResponseData]):
    model_config = ConfigDict(
        from_attributes=True
    )