
import os
from typing import Optional


class CredentialError(Exception):
    """授权配置错误"""
    pass


class Credentials:
    """
    - access_key_id / access_key_secret: 阿里云 AccessKey (OSS/SLS/MNS 共用)
    - oss_endpoint / oss_region: OSS 服务端点和区域
    - sls_endpoint / sls_project / sls_logstore: SLS 日志服务配置
    - mns_endpoint: MNS 消息队列服务端点
    """
    
    # 预设值
    DEFAULT_OSS_ENDPOINT = 'https://oss-cn-shanghai.aliyuncs.com'
    DEFAULT_OSS_REGION = 'cn-shanghai'
    DEFAULT_SLS_ENDPOINT = 'cn-shanghai.log.aliyuncs.com'
    DEFAULT_MNS_ENDPOINT = 'https://1652344617560638.mns.cn-shanghai.aliyuncs.com/'
    
    def __init__(
        self,
        # 阿里云凭证
        access_key_id: Optional[str] = None,
        access_key_secret: Optional[str] = None,
        
        oss_endpoint: str = DEFAULT_OSS_ENDPOINT,
        oss_region: str = DEFAULT_OSS_REGION,
        
        sls_endpoint: str = DEFAULT_SLS_ENDPOINT,
        sls_project: Optional[str] = None,
        sls_logstore: Optional[str] = None,
        
        mns_endpoint: str = DEFAULT_MNS_ENDPOINT,
    ):
        self.access_key_id = access_key_id
        self.access_key_secret = access_key_secret
        self.oss_endpoint = oss_endpoint
        self.oss_region = oss_region
        self.sls_endpoint = sls_endpoint
        self.sls_project = sls_project
        self.sls_logstore = sls_logstore
        self.mns_endpoint = mns_endpoint
        self._oss_provider = None
        self._mns_account = None
    
    @classmethod
    def from_env(cls) -> 'Credentials':
        """
        支持从环境变量加载配置
        - ALIBABA_CLOUD_ACCESS_KEY_ID / ALIBABA_CLOUD_ACCESS_KEY_SECRET
        - OSS_ENDPOINT / OSS_REGION
        - SLS_ENDPOINT / SLS_PROJECT / SLS_LOGSTORE
        - MNS_ENDPOINT
        """
        return cls(
            access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),
            access_key_secret=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
            oss_endpoint=os.environ.get('OSS_ENDPOINT', cls.DEFAULT_OSS_ENDPOINT),
            oss_region=os.environ.get('OSS_REGION', cls.DEFAULT_OSS_REGION),
            sls_endpoint=os.environ.get('SLS_ENDPOINT', cls.DEFAULT_SLS_ENDPOINT),
            sls_project=os.environ.get('SLS_PROJECT'),
            sls_logstore=os.environ.get('SLS_LOGSTORE'),
            mns_endpoint=os.environ.get('MNS_ENDPOINT', cls.DEFAULT_MNS_ENDPOINT),
        )
    
    def _check_access_key(self):
        missing = []
        if not self.access_key_id:
            missing.append('access_key_id (或环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID)')
        if not self.access_key_secret:
            missing.append('access_key_secret (或环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET)')
        if missing:
            raise CredentialError(f"阿里云凭证缺失: {', '.join(missing)}")
    
    def _check_sls_config(self):
        self._check_access_key()
        missing = []
        if not self.sls_project:
            missing.append('sls_project (或环境变量 SLS_PROJECT)')
        if not self.sls_logstore:
            missing.append('sls_logstore (或环境变量 SLS_LOGSTORE)')
        if missing:
            raise CredentialError(f"SLS 配置缺失: {', '.join(missing)}")
    
    def get_oss_provider(self):
        self._check_access_key()
        if self._oss_provider is None:
            from .util_oss import OssCloudObjectProvider
            assert self.access_key_id is not None
            assert self.access_key_secret is not None
            self._oss_provider = OssCloudObjectProvider(
                access_key_id=self.access_key_id,
                access_key_secret=self.access_key_secret,
                endpoint=self.oss_endpoint,
                region=self.oss_region,
            )
        return self._oss_provider
    
    def send_sls_log(self, script_name: str, level: str, message: str, **kwargs):
        self._check_sls_config()
        assert self.access_key_id is not None
        assert self.access_key_secret is not None
        assert self.sls_project is not None
        assert self.sls_logstore is not None
        
        from .aliyun_sls_log import _send_log_to_sls_internal
        _send_log_to_sls_internal(
            script_name=script_name,
            level=level,
            message=message,
            endpoint=self.sls_endpoint,
            project=self.sls_project,
            logstore=self.sls_logstore,
            access_key_id=self.access_key_id,
            access_key_secret=self.access_key_secret,
            **kwargs
        )
    
    def get_mns_account(self):
        self._check_access_key()
        assert self.access_key_id is not None
        assert self.access_key_secret is not None
        if self._mns_account is None:
            import mns.account as mns_account
            self._mns_account = mns_account.Account(
                self.mns_endpoint,
                self.access_key_id,
                self.access_key_secret
            )
        return self._mns_account
    
    def send_mns_message(self, queue_name: str, message_body) -> bool:
        from .mns_client import _send_message_internal
        account = self.get_mns_account()
        return _send_message_internal(account, queue_name, message_body)
    
    def __repr__(self):
        ak_status = "configured" if self.access_key_id else "not configured"
        sls_status = "configured" if self.sls_project else "not configured"
        return f"<Credentials access_key={ak_status}, sls={sls_status}>"
