import base64
import secrets
import subprocess  # noqa: S404
import tempfile
import uuid
from datetime import UTC, datetime
from pathlib import Path
from typing import Any, Literal
from urllib.parse import urlencode

from apps.esia.scopes import SCOPES
from core.config import settings

ACCESS_TYPE = 'online'
RESPONSE_CODE = 'code'


def csp_sign(data: str):
    with tempfile.TemporaryDirectory() as tmp_dir:
        tmp_file_name = secrets.token_hex(8)
        source_path = Path(tmp_dir) / f'{tmp_file_name}.txt'
        destination_path = source_path.with_suffix('.txt.sgn')

        with open(source_path, 'w', encoding='utf-8') as f:
            f.write(data)

        cmd = [
            'cryptcp',
            '-signf',
            '-norev',
            '-nochain',
            '-der',
            '-strict',
            '-cert',
            '-detached',
            '-thumbprint',
            settings.ESIA_CONTAINER_THUMBPRINT,
            '-pin',
            settings.ESIA_CONTAINER_PASSWORD,
            '-dir',
            tmp_dir,
            str(source_path),
        ]

        subprocess.run(  # noqa: S603
            cmd, input=b'y\n', capture_output=True, check=True, text=False
        )
        signed_message = destination_path.read_bytes()

        return signed_message


def sign_params(params: dict[str, Any]):
    plaintext = (
        params.get('scope', '')
        + params.get('timestamp', '')
        + params.get('client_id', '')
        + params.get('state', '')
    )

    client_secret = csp_sign(plaintext)
    return base64.urlsafe_b64encode(client_secret).decode('utf-8')


def get_url(platform: Literal['max', 'app']):
    timestamp = datetime.now(UTC).strftime('%Y.%m.%d %H:%M:%S %z').strip()
    state = str(uuid.uuid4())
    redirect_uri = (
        settings.ESIA_REDIRECT_URI
        if platform == 'app'
        else settings.ESIA_MAX_REDIRECT_URI
    )

    params = {
        'client_id': settings.ESIA_CLIENT_ID,
        'client_secret': '',
        'redirect_uri': redirect_uri,
        'response_type': RESPONSE_CODE,
        'state': state,
        'timestamp': timestamp,
        'access_type': ACCESS_TYPE,
        'scope': ' '.join(SCOPES),
    }
    params['client_secret'] = sign_params(params)

    return f'{settings.ESIA_BASE_URL}/aas/oauth2/ac?{urlencode(params)}'
