from __future__ import annotations

import json
import os
import subprocess
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
    sys.path.insert(0, str(ROOT))

from scripts.db import DB_PATH, init_db, fetch_one
from scripts.repository import create_project, create_scene, create_task, mark_task_submitted, mark_task_submission_failed, update_task_from_callback
from server.callback_receiver import _extract_assets, _authorized
from scripts.scene_router import choose_endpoint


def reset_db():
    if DB_PATH.exists():
        DB_PATH.unlink()
    for suffix in ('-wal', '-shm'):
        p = Path(str(DB_PATH) + suffix)
        if p.exists():
            p.unlink()
    init_db()


def main():
    reset_db()
    create_project('proj_demo', 'Demo Project', 'Reliability validation')
    create_scene({'scene_id':'scene_demo_001','project_id':'proj_demo','ordering':1,'narration':'n','visual_prompt':'v','target_duration':5,'scene_type':'text'})
    # returned task_status respected
    task_id = create_task('scene_demo_001', 'text2video', {'prompt': 'demo'})
    mark_task_submitted(task_id, 'kling_demo_task_001', 'req_demo_001', {'request_id':'req_demo_001','data':{'task_id':'kling_demo_task_001','task_status':'processing'}})
    row1 = fetch_one('SELECT task_status FROM tasks WHERE task_id_internal=?', (task_id,))
    # failed submission persisted
    task_fail = create_task('scene_demo_001', 'text2video', {'prompt':'bad'})
    mark_task_submission_failed(task_fail, 'HTTP 429', 'quota_or_concurrency', 429, 'too many requests')
    row2 = fetch_one('SELECT task_status, task_status_msg FROM tasks WHERE task_id_internal=?', (task_fail,))
    # callback dedupe
    payload = {'task_id':'kling_demo_task_001','task_status':'succeed','task_status_msg':'ok','task_result':{'videos':[{'id':'vid_001','url':'https://example.com/video.mp4','watermark_url':'https://example.com/video_wm.mp4','duration':'5'}]}}
    internal = update_task_from_callback(payload)
    _extract_assets(internal, payload)
    internal2 = update_task_from_callback(payload)
    _extract_assets(internal2, payload)
    asset_count = fetch_one('SELECT COUNT(*) AS cnt FROM assets WHERE source_task_id=?', (internal,))['cnt']
    event_count = fetch_one("SELECT COUNT(*) AS cnt FROM task_events WHERE task_id_internal=? AND event_type='callback'", (internal,))['cnt']
    # router strictness
    routes_ok = {
        'text': choose_endpoint({'scene_type':'text'}),
        'image_ref': choose_endpoint({'scene_type':'image_ref'}),
        'continuity': choose_endpoint({'scene_type':'continuity'}),
        'extend': choose_endpoint({'scene_type':'text','extend_flag':True}),
    }
    unknown_error = None
    try:
        choose_endpoint({'scene_type':'weird'})
    except Exception as e:
        unknown_error = str(e)
    # callback receiver direct entrypoint syntax/import smoke
    try:
        proc = subprocess.run([sys.executable, str(ROOT / 'server' / 'callback_receiver.py')], env={**os.environ, 'KLING_CALLBACK_SHARED_SECRET':'demo-secret'}, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=1)
        direct_start = {'ok': proc.returncode == 0, 'returncode': proc.returncode, 'stderr': proc.stderr.decode('utf-8', errors='ignore')[:200]}
    except subprocess.TimeoutExpired as e:
        direct_start = {'ok': True, 'returncode': 'timeout_running', 'stderr': (e.stderr or b'').decode('utf-8', errors='ignore')[:200]}
    print(json.dumps({
        'ok': True,
        'returned_status': row1,
        'failed_submission': row2,
        'asset_count_after_duplicate_callback': asset_count,
        'callback_event_count_after_duplicate_callback': event_count,
        'routes': routes_ok,
        'unknown_scene_type_error': unknown_error,
        'callback_receiver_direct_start': direct_start,
    }, ensure_ascii=False, indent=2))


if __name__ == '__main__':
    main()
