"""
Installer helpers — paths, requirements checks, .env writer, lock file.
"""
from __future__ import annotations

import os
import secrets
import sys
from pathlib import Path

# Project root = three levels up from apps/installer/utils.py
BASE_DIR = Path(__file__).resolve().parent.parent.parent
LOCK_FILE = BASE_DIR / 'storage' / 'installed'
ENV_FILE = BASE_DIR / '.env'


def is_installed() -> bool:
    return LOCK_FILE.exists()


def mark_installed() -> None:
    LOCK_FILE.parent.mkdir(parents=True, exist_ok=True)
    LOCK_FILE.write_text(
        'installed=true\n'
        f'python={sys.version.split()[0]}\n',
        encoding='utf-8',
    )


def generate_secret_key() -> str:
    return secrets.token_urlsafe(50)


def check_requirements() -> list[dict]:
    """Return a list of requirement check results."""
    checks = []

    py_ok = sys.version_info >= (3, 10)
    checks.append({
        'name': 'Python 3.10+',
        'ok': py_ok,
        'detail': f'{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}',
    })

    for pkg, import_name in [
        ('Django', 'django'),
        ('Pillow', 'PIL'),
        ('python-dotenv', 'dotenv'),
        ('PyMySQL', 'pymysql'),
        ('stripe', 'stripe'),
    ]:
        try:
            __import__(import_name)
            ok, detail = True, 'Installed'
        except ImportError:
            ok, detail = False, f'Missing — run: pip install {pkg}'
        checks.append({'name': pkg, 'ok': ok, 'detail': detail})

    writable_paths = [
        BASE_DIR,
        BASE_DIR / 'media',
        BASE_DIR / 'logs',
        BASE_DIR / 'storage',
    ]
    for path in writable_paths:
        path.mkdir(parents=True, exist_ok=True)
        ok = os.access(path, os.W_OK)
        rel = '.' if path == BASE_DIR else str(path.relative_to(BASE_DIR))
        checks.append({
            'name': f'Writable: {rel}',
            'ok': ok,
            'detail': 'OK' if ok else 'Not writable — fix folder permissions',
        })

    return checks


def all_requirements_ok(checks=None) -> bool:
    checks = checks or check_requirements()
    return all(c['ok'] for c in checks)


def write_env(data: dict) -> None:
    """Write .env from installer form data."""
    lines = [
        f"DEBUG={data.get('debug', 'True')}",
        f"SECRET_KEY={data.get('secret_key') or generate_secret_key()}",
        f"ALLOWED_HOSTS={data.get('allowed_hosts', 'localhost,127.0.0.1')}",
        '',
        f"DB_ENGINE={data.get('db_engine', 'sqlite3')}",
        f"DB_NAME={data.get('db_name', 'db.sqlite3')}",
        f"DB_USER={data.get('db_user', '')}",
        f"DB_PASSWORD={data.get('db_password', '')}",
        f"DB_HOST={data.get('db_host', '127.0.0.1')}",
        f"DB_PORT={data.get('db_port', '3306')}",
        '',
        'EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend',
        f"DEFAULT_FROM_EMAIL={data.get('institute_name', 'Academy')} <noreply@localhost>",
        '',
    ]
    ENV_FILE.write_text('\n'.join(lines) + '\n', encoding='utf-8')


def test_mysql_connection(user, password, host, port, name) -> tuple[bool, str]:
    try:
        import pymysql
        conn = pymysql.connect(
            host=host or '127.0.0.1',
            user=user or 'root',
            password=password or '',
            port=int(port or 3306),
            database=name or None,
            connect_timeout=5,
        )
        conn.close()
        return True, 'Connected successfully'
    except Exception as exc:
        return False, str(exc)


def validate_admin(username, email, password) -> list[str]:
    errors = []
    if not username or len(username) < 3:
        errors.append('Admin username must be at least 3 characters.')
    if not email or '@' not in email:
        errors.append('Enter a valid admin email.')
    if not password or len(password) < 8:
        errors.append('Admin password must be at least 8 characters.')
    return errors


def sanitize_hosts(raw: str) -> str:
    hosts = [h.strip() for h in (raw or '').split(',') if h.strip()]
    if 'localhost' not in hosts:
        hosts.insert(0, 'localhost')
    if '127.0.0.1' not in hosts:
        hosts.insert(1, '127.0.0.1')
    return ','.join(hosts)
