"""
pghoard

Copyright (c) 2015 Ohmu Ltd
See LICENSE for details
"""
from .base import PGHoardTestCase
from dateutil import tz
from pghoard.restore import create_recovery_conf, Restore, RestoreError
from unittest.mock import Mock
import datetime
import os
import pytest


class TestRecoveryConf(PGHoardTestCase):
    def test_recovery_targets(self, tmpdir):
        r = Restore()
        r._load_config = Mock()  # pylint: disable=protected-access
        r._get_object_storage = Mock()  # pylint: disable=protected-access
        with pytest.raises(RestoreError) as excinfo:
            r.run(args=[
                "get-basebackup",
                "--config=" + str(tmpdir),
                "--target-dir=" + str(tmpdir),
                "--site=test",
                "--recovery-target-action=promote",
                "--recovery-target-name=foobar",
                "--recovery-target-xid=42",
            ])
        assert "at most one" in str(excinfo.value)
        with pytest.raises(RestoreError) as excinfo:
            r.run(args=[
                "get-basebackup",
                "--config=" + str(tmpdir),
                "--target-dir=" + str(tmpdir),
                "--site=test",
                "--recovery-target-action=promote",
                "--recovery-target-time=foobar",
            ])
        assert "recovery_target_time 'foobar'" in str(excinfo.value)

    def test_find_nearest_backup(self):
        r = Restore()
        r.storage = Mock()
        basebackups = [{"name": "2015-02-12_0", "metadata": {"start-time": "2015-02-12T14:07:19+00:00"}},
                       {"name": "2015-02-13_0", "metadata": {"start-time": "2015-02-13T14:07:19+00:00"}}]

        r.storage.list_basebackups = Mock(return_value=basebackups)
        assert r._find_nearest_basebackup() == "2015-02-13_0"  # pylint: disable=protected-access
        utc = tz.tzutc()
        recovery_time = datetime.datetime(2015, 2, 1)
        recovery_time = recovery_time.replace(tzinfo=utc)
        with pytest.raises(RestoreError):
            r._find_nearest_basebackup(recovery_time)  # pylint: disable=protected-access

        recovery_time = datetime.datetime(2015, 2, 12, 14, 20)
        recovery_time = recovery_time.replace(tzinfo=utc)
        assert r._find_nearest_basebackup(recovery_time) == "2015-02-12_0"  # pylint: disable=protected-access

    def test_create_recovery_conf(self):
        td = self.temp_dir
        fn = os.path.join(td, "recovery.conf")

        def getdata():
            with open(fn, "r") as fp:
                return fp.read()

        assert not os.path.exists(fn)
        create_recovery_conf(td, "dummysite", None)
        assert "primary_conninfo" not in getdata()
        create_recovery_conf(td, "dummysite", "")
        assert "primary_conninfo" not in getdata()
        create_recovery_conf(td, "dummysite", "dbname='test'")
        assert "primary_conninfo" in getdata()  # make sure it's there
        assert "''test''" in getdata()  # make sure it's quoted
        assert "standby_mode = 'on'" in getdata()
        content = create_recovery_conf(td, "dummysite", "dbname='test'", restore_to_master=True)
        assert "primary_conninfo" in content
        assert "standby_mode = 'on'" not in content
        content = create_recovery_conf(td, "dummysite",
                                       recovery_end_command="echo 'done' > /tmp/done",
                                       recovery_target_xid="42")
        assert content == getdata()
        assert "primary_conninfo" not in content
        assert "recovery_end_command = 'echo ''done'' > /tmp/done'" in content

        # NOTE: multiple recovery targets don't really make sense in
        # recovery.conf: PostgreSQL just uses the last entry.
        # create_recovery_conf doesn't check them as it's called late enough
        # for that check to be useless.  Let's just make sure we can write
        # lines for all of them.
        now = datetime.datetime.now()
        content = create_recovery_conf(td, "dummysite",
                                       recovery_end_command="/bin/false",
                                       recovery_target_action="shutdown",
                                       recovery_target_name="testpoint",
                                       recovery_target_time=now,
                                       recovery_target_xid="42")
        assert "recovery_target_action" in content
        assert "recovery_target_name" in content
        assert "recovery_target_time" in content
        assert "recovery_target_xid" in content
        assert str(now) in content
