from __future__ import annotations

from typing import TYPE_CHECKING

from mipac.abstract.model import AbstractModel
from mipac.models.lite.meta import LiteMeta, MetaCommon
from mipac.types.meta import IAdminMeta, IFeatures, IMeta, IPolicies

if TYPE_CHECKING:
    from mipac.manager.client import ClientManager


class Policies(AbstractModel):
    def __init__(self, policies: IPolicies) -> None:
        self.__policies: IPolicies = policies

    @property
    def gtl_available(self) -> bool:
        return self.__policies["gtl_available"]

    @property
    def ltl_available(self) -> bool:
        return self.__policies["ltl_available"]

    @property
    def can_public_note(self) -> bool:
        return self.__policies["can_public_note"]

    @property
    def can_invite(self) -> bool:
        return self.__policies["can_invite"]

    @property
    def can_manage_custom_emojis(self) -> bool:
        return self.__policies["can_manage_custom_emojis"]

    @property
    def can_hide_ads(self) -> bool:
        return self.__policies["can_hide_ads"]

    @property
    def drive_capacity_mb(self) -> int:
        return self.__policies["drive_capacity_mb"]

    @property
    def pin_limit(self) -> int:
        return self.__policies["pin_limit"]

    @property
    def antenna_limit(self) -> int:
        return self.__policies["antenna_limit"]

    @property
    def word_mute_limit(self) -> int:
        return self.__policies["word_mute_limit"]

    @property
    def webhook_limit(self) -> int:
        return self.__policies["webhook_limit"]

    @property
    def clip_limit(self) -> int:
        return self.__policies["clip_limit"]

    @property
    def note_each_clips_limit(self) -> int:
        return self.__policies["note_each_clips_limit"]

    @property
    def user_list_limit(self) -> int:
        return self.__policies["user_list_limit"]

    @property
    def user_each_user_lists_limit(self) -> int:
        return self.__policies["user_each_user_lists_limit"]

    @property
    def rate_limit_factor(self) -> int:
        return self.__policies["rate_limit_factor"]


class Features(AbstractModel):
    def __init__(self, features: IFeatures) -> None:
        self.__features = features

    @property
    def registration(self) -> bool:
        return self.__features["registration"]

    @property
    def elasticsearch(self) -> bool:
        return self.__features["elasticsearch"]

    @property
    def hcaptcha(self) -> bool:
        return self.__features["hcaptcha"]

    @property
    def recaptcha(self) -> bool:
        return self.__features["recaptcha"]

    @property
    def object_storage(self) -> bool:
        return self.__features["object_storage"]

    @property
    def twitter(self) -> bool:
        return self.__features["twitter"]

    @property
    def github(self) -> bool:
        return self.__features["github"]

    @property
    def discord(self) -> bool:
        return self.__features["discord"]

    @property
    def service_worker(self) -> bool:
        return self.__features["service_worker"]

    @property
    def miauth(self) -> bool:
        return self.__features.get("miauth", False)

    @property
    def email_required_for_signup(self) -> bool:
        return self.__features.get("email_required_for_signup", False)

    @property
    def global_time_line(self) -> bool:
        return self.__features.get("global_time_line", False)

    @property
    def local_time_line(self) -> bool:
        return self.__features.get("local_time_line", False)


class Meta(LiteMeta):
    def __init__(self, meta: IMeta, *, client: ClientManager) -> None:
        super().__init__(meta, client=client)
        self.__meta = meta

    # shared

    @property
    def features(self) -> Features:
        return Features(self.__meta["features"])

    # v12

    @property
    def pinned_clip_id(self) -> str | None:
        return self.__meta.get("pinned_clip_id")

    @property
    def pinned_pages(self) -> list[str]:
        return self.__meta.get("pinned_pages", [])

    @property
    def policies(self) -> Policies | None:
        return Policies(self.__meta["policies"]) if "policies" in self.__meta else None

    @property
    def require_setup(self) -> bool:
        return self.__meta.get("require_setup", False)


class AdminMeta(MetaCommon):
    def __init__(self, admin_meta: IAdminMeta, *, client: ClientManager) -> None:
        super().__init__(admin_meta, client=client)
        self.__admin_meta = admin_meta

    # 全てのバージョン共通に存在する

    @property
    def drive_capacity_per_local_user_mb(self) -> int | None:
        return self.__admin_meta.get("drive_capacity_per_local_user_mb")

    @property
    def drive_capacity_per_remote_user_mb(self) -> int | None:
        return self.__admin_meta.get("drive_capacity_per_remote_user_mb")

    @property
    def hidden_tags(self) -> list[str]:
        return self.__admin_meta.get("hidden_tags", [])

    @property
    def blocked_hosts(self) -> list[str]:
        return self.__admin_meta.get("blocked_hosts", [])

    @property
    def recaptcha_secret_key(self) -> str | None:
        return self.__admin_meta.get("recaptcha_secret_key")

    @property
    def twitter_consumer_key(self) -> str | None:
        return self.__admin_meta.get("twitter_consumer_key")

    @property
    def twitter_consumer_secret(self) -> str | None:
        return self.__admin_meta.get("twitter_consumer_secret")

    @property
    def github_client_id(self) -> str | None:
        return self.__admin_meta.get("github_client_id")

    @property
    def github_client_secret(self) -> str | None:
        return self.__admin_meta.get("github_client_secret")

    @property
    def discord_client_id(self) -> str | None:
        return self.__admin_meta.get("discord_client_id")

    @property
    def discord_client_secret(self) -> str | None:
        return self.__admin_meta.get("discord_client_secret")

    @property
    def email(self) -> str | None:
        return self.__admin_meta.get("email")

    @property
    def smtp_secure(self) -> bool:
        return self.__admin_meta.get("smtp_secure", False)

    @property
    def smtp_host(self) -> str | None:
        return self.__admin_meta.get("smtp_host")

    @property
    def smtp_port(self) -> int | None:
        return self.__admin_meta.get("smtp_port")

    @property
    def smtp_user(self) -> str | None:
        return self.__admin_meta.get("smtp_user")

    @property
    def smtp_pass(self) -> str | None:
        return self.__admin_meta.get("smtp_pass")

    @property
    def sw_private_key(self) -> str | None:
        return self.__admin_meta.get("sw_private_key")

    @property
    def use_object_storage(self) -> bool:
        return self.__admin_meta.get("use_object_storage", False)

    @property
    def object_storage_base_url(self) -> str | None:
        return self.__admin_meta.get("object_storage_base_url")

    @property
    def object_storage_bucket(self) -> str | None:
        return self.__admin_meta.get("object_storage_bucket")

    @property
    def object_storage_prefix(self) -> str | None:
        return self.__admin_meta.get("object_storage_prefix")

    @property
    def object_storage_endpoint(self) -> str | None:
        return self.__admin_meta.get("object_storage_endpoint")

    @property
    def object_storage_region(self) -> str | None:
        return self.__admin_meta.get("object_storage_region")

    @property
    def object_storage_port(self) -> int | None:
        return self.__admin_meta.get("object_storage_port")

    @property
    def object_storage_access_key(self) -> str | None:
        return self.__admin_meta.get("object_storage_access_key")

    @property
    def object_storage_secret_key(self) -> str | None:
        return self.__admin_meta.get("object_storage_secret_key")

    @property
    def object_storage_use_ssl(self) -> bool:
        return self.__admin_meta.get("object_storage_use_ssl", False)

    @property
    def object_storage_use_proxy(self) -> bool:
        return self.__admin_meta.get("object_storage_use_proxy", False)

    @property
    def object_storage_set_public_read(self) -> bool:
        return self.__admin_meta.get("object_storage_set_public_read", False)

    @property
    def pinned_users(self) -> list[str]:
        return self.__admin_meta.get("pinned_users", [])

    """
    v12 only
    """

    @property
    def hcaptcha_secret_key(self) -> str | None:
        return self.__admin_meta.get("hcaptcha_secret_key")

    @property
    def sensitive_media_detection(self) -> str | None:
        return self.__admin_meta.get("sensitive_media_detection")

    @property
    def sensitive_media_detection_sensitivity(self) -> str | None:
        return self.__admin_meta.get("sensitive_media_detection_sensitivity")

    @property
    def set_sensitive_flag_automatically(self) -> bool:
        return self.__admin_meta.get("set_sensitive_flag_automatically", False)

    @property
    def enable_sensitive_media_detection_for_videos(self) -> bool:
        return self.__admin_meta.get("enable_sensitive_media_detection_for_videos", False)

    @property
    def proxy_account_id(self) -> str | None:
        return self.__admin_meta.get("proxy_account_id")

    @property
    def summary_proxy(self) -> str | None:
        return self.__admin_meta.get("summary_proxy")

    @property
    def enable_ip_logging(self) -> bool:
        return self.__admin_meta.get("enable_ip_logging", False)

    @property
    def enable_active_email_validation(self) -> bool:
        return self.__admin_meta.get("enable_active_email_validation", False)
