"""Tests for duty_teller.api.dependencies (lang, auth error, date validation, private client)."""

from unittest.mock import patch

import pytest
from fastapi import HTTPException

import duty_teller.api.dependencies as deps
import duty_teller.config as config


class TestLangFromAcceptLanguage:
    """Tests for _lang_from_accept_language: always returns config.DEFAULT_LANGUAGE."""

    def test_always_returns_default_language(self):
        """Header is ignored; result is always config.DEFAULT_LANGUAGE."""
        assert deps._lang_from_accept_language(None) == config.DEFAULT_LANGUAGE
        assert deps._lang_from_accept_language("") == config.DEFAULT_LANGUAGE
        assert deps._lang_from_accept_language("   ") == config.DEFAULT_LANGUAGE
        assert (
            deps._lang_from_accept_language("ru-RU,ru;q=0.9") == config.DEFAULT_LANGUAGE
        )
        assert deps._lang_from_accept_language("en-US") == config.DEFAULT_LANGUAGE
        assert deps._lang_from_accept_language("zz") == config.DEFAULT_LANGUAGE
        assert deps._lang_from_accept_language("x") == config.DEFAULT_LANGUAGE

    def test_returns_ru_when_default_language_is_ru(self):
        with patch.object(config, "DEFAULT_LANGUAGE", "ru"):
            assert deps._lang_from_accept_language("en-US") == "ru"
            assert deps._lang_from_accept_language(None) == "ru"

    def test_returns_en_when_default_language_is_en(self):
        with patch.object(config, "DEFAULT_LANGUAGE", "en"):
            assert deps._lang_from_accept_language("ru-RU") == "en"
            assert deps._lang_from_accept_language(None) == "en"


class TestAuthErrorDetail:
    """Tests for _auth_error_detail."""

    def test_hash_mismatch_uses_bad_signature_key(self):
        with patch("duty_teller.api.dependencies.t") as mock_t:
            mock_t.return_value = "Bad signature"
            result = deps._auth_error_detail("hash_mismatch", "en")
        assert result == "Bad signature"
        mock_t.assert_called_once_with("en", "api.auth_bad_signature")

    def test_other_reason_uses_auth_invalid_key(self):
        with patch("duty_teller.api.dependencies.t") as mock_t:
            mock_t.return_value = "Invalid auth"
            result = deps._auth_error_detail("expired", "ru")
        assert result == "Invalid auth"
        mock_t.assert_called_once_with("ru", "api.auth_invalid")


class TestValidateDutyDates:
    """Tests for _validate_duty_dates."""

    def test_valid_range_no_exception(self):
        deps._validate_duty_dates("2025-01-01", "2025-01-31", "en")

    def test_bad_format_raises_400_with_i18n(self):
        with patch("duty_teller.api.dependencies.t") as mock_t:
            mock_t.return_value = "Bad format message"
            with pytest.raises(HTTPException) as exc_info:
                deps._validate_duty_dates("01-01-2025", "2025-01-31", "en")
        assert exc_info.value.status_code == 400
        assert exc_info.value.detail == "Bad format message"
        mock_t.assert_called_with("en", "dates.bad_format")

    def test_from_after_to_raises_400_with_i18n(self):
        with patch("duty_teller.api.dependencies.t") as mock_t:
            mock_t.return_value = "From after to message"
            with pytest.raises(HTTPException) as exc_info:
                deps._validate_duty_dates("2025-02-01", "2025-01-01", "ru")
        assert exc_info.value.status_code == 400
        assert exc_info.value.detail == "From after to message"
        mock_t.assert_called_with("ru", "dates.from_after_to")


class TestFetchDutiesResponse:
    """Tests for fetch_duties_response (DutyWithUser list with phone, username)."""

    def test_fetch_duties_response_includes_phone_and_username(self):
        """get_duties returns (Duty, full_name, phone, username); response has phone, username."""
        from types import SimpleNamespace

        from duty_teller.db.schemas import DutyWithUser

        duty = SimpleNamespace(
            id=1,
            user_id=10,
            start_at="2025-01-15T09:00:00Z",
            end_at="2025-01-15T18:00:00Z",
            event_type="duty",
        )
        rows = [(duty, "Alice", "+79001234567", "alice_dev")]
        with patch.object(deps, "get_duties", return_value=rows):
            result = deps.fetch_duties_response(
                type("Session", (), {})(), "2025-01-01", "2025-01-31"
            )
        assert len(result) == 1
        assert isinstance(result[0], DutyWithUser)
        assert result[0].full_name == "Alice"
        assert result[0].phone == "+79001234567"
        assert result[0].username == "alice_dev"
