"""Pydantic models for APK information."""

from pathlib import Path

from pydantic import BaseModel


class AppMetadata(BaseModel):
    """Shared package identity fields — source-agnostic base model."""

    package_name: str
    """Full package name (e.g., com.example.app)."""

    version_name: str | None = None
    """Version string (e.g., 1.0.0)."""

    version_code: int | None = None
    """Version code (e.g., 100)."""

    min_sdk: int | None = None
    """Minimum SDK version (e.g., 21)."""

    target_sdk: int | None = None
    """Target SDK (e.g., 35)."""


class PackageInfo(AppMetadata):
    """Basic package information from a device."""

    app_name: str | None = None
    """Human-readable application name."""

    signing_version: int | None = None
    """APK signing version (e.g., 3)."""

    apk_path: str | None = None
    """Path to the base APK on device."""

    split_apks: list[str] | None = None
    """Paths to split APKs on device (if app is split)."""

    @property
    def is_split(self) -> bool:
        """Check if this is a split APK."""
        return bool(self.split_apks and len(self.split_apks) > 0)

    @property
    def all_apk_paths(self) -> list[str]:
        """Get all APK paths (base + splits)."""
        paths = []
        if self.apk_path:
            paths.append(self.apk_path)
        if self.split_apks:
            paths.extend(self.split_apks)
        return paths


class PulledAPK(BaseModel):
    """Result of pulling an APK from a device."""

    package_name: str
    """Package name of the pulled app."""

    local_path: Path
    """Local path where APK was saved."""

    is_split: bool = False
    """Whether multiple APKs were pulled."""

    split_paths: list[Path] | None = None
    """Paths to split APKs (if split)."""

    merged_path: Path | None = None
    """Path to merged APK (if split APKs were combined)."""

    @property
    def all_paths(self) -> list[Path]:
        """Get all pulled APK paths."""
        if self.split_paths:
            return self.split_paths
        return [self.local_path]

    @property
    def final_apk_path(self) -> Path | None:
        """Best APK candidate for downstream actions (merge result or single APK)."""
        if self.is_split:
            return self.merged_path
        return self.local_path


class PatchResult(BaseModel):
    """Result of patching an APK from apktool directory."""

    source_dir: Path
    """Original apktool directory."""

    output_path: Path
    """Final output APK path."""

    signed: bool = False
    """Whether APK was signed."""

    aligned: bool = False
    """Whether APK was aligned."""

    verified: bool | None = None
    """Signature verification result. None if not verified."""

    keystore_generated: bool = False
    """Whether a debug keystore was auto-generated."""


class DecompileResult(BaseModel):
    """Result of decompiling an APK."""

    apk_path: Path
    """Original APK path."""

    output_dir: Path
    """Root output directory containing java/ and smali/ subdirs."""

    java_dir: Path | None = None
    """Java source output directory (jadx). None if not requested."""

    smali_dir: Path | None = None
    """Smali/resources output directory (apktool). None if not requested."""

    java_success: bool = False
    """Whether jadx decompilation succeeded."""

    smali_success: bool = False
    """Whether apktool decompilation succeeded."""
