import json

from app.db import connect, execute, init_db, query_one, set_setting, transaction, utcnow
from app.services.automation_engine import AutomationEngine


def make_automation(reply_mode='sequential'):
    now = utcnow()
    aid = execute('INSERT INTO automations(name,enabled,trigger_type,media_scope,reply_mode,created_at,updated_at) VALUES (?,?,?,?,?,?,?)', ('test-auto',1,'comment','all',reply_mode,now,now))
    execute('INSERT INTO automation_keywords(automation_id,keyword,match_type) VALUES (?,?,?)', (aid,'5','exact'))
    execute('INSERT INTO comment_replies(automation_id,text,position) VALUES (?,?,?)', (aid,'one',0))
    execute('INSERT INTO comment_replies(automation_id,text,position) VALUES (?,?,?)', (aid,'two',1))
    return aid


def test_integrity_and_duplicate_constraints():
    init_db()
    conn = connect()
    assert conn.execute('PRAGMA integrity_check').fetchone()[0] == 'ok'
    conn.close()
    execute('INSERT OR IGNORE INTO processed_comments(comment_id,processed_at) VALUES (?,?)', ('dup-comment', utcnow()))
    execute('INSERT OR IGNORE INTO processed_comments(comment_id,processed_at) VALUES (?,?)', ('dup-comment', utcnow()))
    assert query_one('SELECT COUNT(*) AS c FROM processed_comments WHERE comment_id=?', ('dup-comment',))['c'] == 1
    execute('INSERT OR IGNORE INTO processed_messages(message_id,processed_at) VALUES (?,?)', ('dup-message', utcnow()))
    execute('INSERT OR IGNORE INTO processed_messages(message_id,processed_at) VALUES (?,?)', ('dup-message', utcnow()))
    assert query_one('SELECT COUNT(*) AS c FROM processed_messages WHERE message_id=?', ('dup-message',))['c'] == 1


def test_sequential_reply_persists():
    aid = make_automation('sequential')
    engine = AutomationEngine()
    automation = query_one('SELECT * FROM automations WHERE id=?', (aid,))
    assert engine._choose_comment_reply(automation) == 'one'
    automation = query_one('SELECT * FROM automations WHERE id=?', (aid,))
    assert engine._choose_comment_reply(automation) == 'two'
    automation = query_one('SELECT * FROM automations WHERE id=?', (aid,))
    assert engine._choose_comment_reply(automation) == 'one'


def test_conversation_state_and_dry_run():
    aid = make_automation('random')
    execute('INSERT INTO automation_steps(automation_id,position,step_type,config_json) VALUES (?,?,?,?)', (aid,0,'send_text_dm',json.dumps({'text':'hello'})))
    execute('INSERT INTO automation_steps(automation_id,position,step_type,config_json) VALUES (?,?,?,?)', (aid,1,'wait_for_user_message',json.dumps({'keywords':['done']})))
    set_setting('dry_run','1')
    engine = AutomationEngine()
    auto = query_one('SELECT * FROM automations WHERE id=?', (aid,))
    result = engine.execute(object(), auto, {'user_id':'123','username':'u','thread_id':'9','trigger_type':'dm'})
    assert result['sent'] == 0
    state = query_one('SELECT * FROM conversation_states WHERE instagram_user_id=? AND automation_id=?', ('123',aid))
    assert state and state['state'] == 'WAITING_FOR_USER_MESSAGE'


def test_random_reply(monkeypatch):
    aid = make_automation('random')
    engine = AutomationEngine()
    automation = query_one('SELECT * FROM automations WHERE id=?', (aid,))
    monkeypatch.setattr('app.services.automation_engine.random.choice', lambda values: values[-1])
    assert engine._choose_comment_reply(automation) == 'two'


def test_debug_mode_setting():
    from app.db import get_bool
    set_setting('debug_mode', '1')
    assert get_bool('debug_mode') is True
    set_setting('debug_mode', '0')
    assert get_bool('debug_mode') is False
