"""Tests for mldash._credentials — local credential storage."""
import json
import os
import stat

import pytest

from mldash._credentials import clear, get, load, store


class TestCredentialStorage:
    def test_load_returns_empty_when_no_file(self, creds_dir):
        assert load() == {}

    def test_store_and_load(self, creds_dir):
        store(url='http://localhost:8000', api_key='mldash_test123')
        creds = load()
        assert creds['url'] == 'http://localhost:8000'
        assert creds['api_key'] == 'mldash_test123'

    def test_store_preserves_existing(self, creds_dir):
        store(url='http://localhost:8000', api_key='mldash_abc')
        store(project_id=42)
        creds = load()
        assert creds['url'] == 'http://localhost:8000'
        assert creds['api_key'] == 'mldash_abc'
        assert creds['project_id'] == 42

    def test_store_overwrites_field(self, creds_dir):
        store(url='http://old.example.com')
        store(url='http://new.example.com')
        assert load()['url'] == 'http://new.example.com'

    def test_clear_removes_file(self, creds_dir):
        store(url='http://localhost:8000')
        clear()
        assert load() == {}

    def test_clear_noop_when_no_file(self, creds_dir):
        clear()  # should not raise

    def test_get_returns_value(self, creds_dir):
        store(url='http://localhost:8000', api_key='mldash_xyz')
        assert get('url') == 'http://localhost:8000'
        assert get('api_key') == 'mldash_xyz'

    def test_get_returns_default_for_missing(self, creds_dir):
        assert get('nonexistent') is None
        assert get('nonexistent', 'fallback') == 'fallback'

    def test_file_permissions(self, creds_dir):
        store(url='http://localhost:8000')
        creds_file = creds_dir / 'credentials'
        mode = os.stat(creds_file).st_mode
        # Owner read+write only (0o600)
        assert mode & stat.S_IRUSR  # owner read
        assert mode & stat.S_IWUSR  # owner write
        assert not (mode & stat.S_IRGRP)  # no group read
        assert not (mode & stat.S_IROTH)  # no other read

    def test_handles_corrupt_json(self, creds_dir):
        creds_file = creds_dir / 'credentials'
        creds_file.write_text('not valid json {{{')
        assert load() == {}

    def test_creates_directory(self, tmp_path):
        nested = tmp_path / 'deep' / 'nested'
        old = os.environ.get('MLDASH_CONFIG_DIR')
        os.environ['MLDASH_CONFIG_DIR'] = str(nested)
        try:
            store(url='http://localhost:8000')
            assert (nested / 'credentials').exists()
        finally:
            if old is not None:
                os.environ['MLDASH_CONFIG_DIR'] = old
            else:
                os.environ.pop('MLDASH_CONFIG_DIR', None)
