from __future__ import annotations

import pytest
from pydantic import ValidationError as PydanticValidationError

from app.config import Settings
from app.database.models import MediaAsset, MediaStatus, Post
from app.errors import ValidationError
from app.services.templates import parse_buttons, render_caption, resolve_cover
from app.utils.validation import (
    parse_duration_seconds,
    parse_local_datetime,
    validate_buttons_json,
    validate_http_url,
)
from tests.conftest import make_settings


def test_settings_rejects_bad_token_and_empty_admins(tmp_path):
    with pytest.raises(PydanticValidationError):
        Settings(
            bot_token="not-a-token",
            admin_ids=[1],
            database_url=f"sqlite+aiosqlite:///{(tmp_path / 'x.db').as_posix()}",
        )
    with pytest.raises(PydanticValidationError):
        Settings(
            bot_token="123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi",
            admin_ids=[],
            database_url=f"sqlite+aiosqlite:///{(tmp_path / 'x.db').as_posix()}",
        )


def test_settings_safe_summary_never_contains_token(tmp_path):
    settings = make_settings(tmp_path)
    summary = settings.safe_summary()
    assert "token" not in summary
    assert settings.bot_token.get_secret_value() not in str(summary)


def test_settings_accepts_comma_separated_admin_ids(tmp_path):
    settings = Settings(
        bot_token="123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi",
        admin_ids="111,222,111",
        database_url=f"sqlite+aiosqlite:///{(tmp_path / 'x.db').as_posix()}",
    )
    assert settings.admin_ids == [111, 222]


def test_duration_parser_supports_minutes_hours_and_persian_units():
    assert parse_duration_seconds("30") == 30
    assert parse_duration_seconds("15m") == 900
    assert parse_duration_seconds("2h") == 7200
    assert parse_duration_seconds("۲ ساعت") == 7200
    assert parse_duration_seconds("10 دقیقه") == 600
    with pytest.raises(ValidationError):
        parse_duration_seconds("8d")


def test_local_datetime_round_trip_is_utc():
    from zoneinfo import ZoneInfo

    value = parse_local_datetime("2026-12-31 21:30", ZoneInfo("Asia/Tehran"))
    assert value.tzinfo is not None
    assert value.hour == 18  # 21:30 Tehran == 18:00 UTC


def test_url_and_button_validation_blocks_local_and_bad_schemes():
    assert validate_http_url("https://t.me/example") == "https://t.me/example"
    for bad in ("ftp://example.com", "https://localhost/x", "https://user:pass@example.com"):
        with pytest.raises(ValidationError):
            validate_http_url(bad)
    buttons = validate_buttons_json('[{"text":"Join","url":"https://t.me/example"}]')
    assert buttons[0]["text"] == "Join"
    with pytest.raises(ValidationError):
        validate_buttons_json("not-json")


def test_caption_variables_and_priority():
    post = Post(
        id=7,
        media_asset_id=1,
        title="Title",
        description="Description",
        video_link="https://t.me/smoke_bot?start=abc",
        published_at=None,
    )
    post.media_asset = MediaAsset(
        id=1,
        source_chat_id=1,
        source_message_id=1,
        file_id="f",
        file_unique_id="u",
        media_type="video",
        status=MediaStatus.READY,
        file_name="clip.mp4",
    )
    text = render_caption(
        template="{title}|{description}|{video_link}|{post_id}|{channel_name}|{brand}|{media_file_name}",
        title=post.title,
        description=post.description,
        video_link=post.video_link,
        post_id=post.id,
        publish_date=post.published_at,
        channel_name="Channel",
        channel_username="channel_user",
        brand="Brand",
        media_file_name="clip.mp4",
    )
    assert "Title" in text and "Description" in text
    assert "https://t.me/smoke_bot?start=abc" in text
    assert "Channel" in text and "Brand" in text and "clip.mp4" in text


def test_caption_override_is_used_and_buttons_parse():
    post = Post(
        id=1,
        media_asset_id=1,
        caption_override="Hello {title}",
        title="T",
    )
    post.buttons_override = [{"text": "A", "url": "https://example.com"}]
    assert parse_buttons(post.buttons_override) == [("A", "https://example.com")]
    assert resolve_cover(post, global_cover="global", use_media_thumbnail=True) == "global"
