from cmdbox.app import common
from cmdbox.app.features.cli import cmdbox_web_start
from cmdbox.app.options import Options
from iinfer.app import web
from pathlib import Path
from typing import Dict, Any, Tuple, List
from urllib.request import pathname2url
import argparse
import logging
import traceback


class WebStart(cmdbox_web_start.WebStart):
    def get_option(self):
        """
        この機能のオプションを返します

        Returns:
            Dict[str, Any]: オプション
        """
        opt = super().get_option()
        opt["choice"] += [
            dict(opt="showimg_html", type=Options.T_FILE, default=None, required=False, multi=False, hide=False, choice=None,
                 discription_ja="`showimg.html` を指定します。省略時はiinfer内蔵のHTMLファイルを使用します。",
                 discription_en="Specify `showimg.html`. If omitted, the iinfer built-in HTML file is used."),
            dict(opt="webcap_html", type=Options.T_FILE, default=None, required=False, multi=False, hide=False, choice=None,
                 discription_ja="`webcap.html` を指定します。省略時はiinfer内蔵のHTMLファイルを使用します。",
                 discription_en="Specify `webcap.html`. If omitted, the iinfer built-in HTML file is used."),
            dict(opt="anno_html", type=Options.T_FILE, default=None, required=False, multi=False, hide=False, choice=None,
                 discription_ja="`annotation.html` を指定します。省略時はiinfer内蔵のHTMLファイルを使用します。",
                 discription_en="Specify `annotation.html`. If omitted, the iinfer built-in HTML file is used."),
        ]
        return opt

    def apprun(self, logger:logging.Logger, args:argparse.Namespace, tm:float, pf:List[Dict[str, float]]=[]) -> Tuple[int, Dict[str, Any], Any]:
        """
        この機能の実行を行います

        Args:
            logger (logging.Logger): ロガー
            args (argparse.Namespace): 引数
            tm (float): 実行開始時間
            pf (List[Dict[str, float]]): 呼出元のパフォーマンス情報

        Returns:
            Tuple[int, Dict[str, Any], Any]: 終了コード, 結果, オブジェクト
        """
        if args.data is None:
            msg = {"warn":f"Please specify the --data option."}
            common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
            return 1, msg
        w = None
        try:
            ssl_cert = None if args.ssl_cert is None else Path(args.ssl_cert)
            ssl_key = None if args.ssl_key is None else Path(args.ssl_key)
            ssl_ca_certs = None if args.ssl_ca_certs is None else Path(args.ssl_ca_certs)
            w = web.Web(logger, Path(args.data), appcls=self.appcls, ver=self.ver,
                        redis_host=args.host, redis_port=args.port, redis_password=args.password, svname=args.svname,
                        client_only=args.client_only, doc_root=args.doc_root, gui_html=args.gui_html, filer_html=args.filer_html, assets=args.assets,
                        signin_html=args.signin_html, signin_file=args.signin_file, gui_mode=False,
                        showimg_html=args.showimg_html, webcap_html=args.webcap_html, anno_html=args.anno_html)
            agent_runner = None
            mcp = None
            logger.info(f"Agent={args.agent}")
            if args.agent=='use':
                if args.agent_session_store == 'sqlite':
                    args.agent_session_dburl = "sqlite://" + pathname2url(str(w.agent_path / 'session.db'))
                elif args.agent_session_store == 'postgresql':
                    args.agent_session_dburl = f"postgresql+psycopg://{args.agent_pg_user}:{args.agent_pg_password}@{args.agent_pg_host}:{args.agent_pg_port}/{args.agent_pg_dbname}"
                else:
                    args.agent_session_dburl = None
                agent_runner, mcp = self.init_agent_runner(logger, args)
            w.start(allow_host=args.allow_host, listen_port=args.listen_port, ssl_listen_port=args.ssl_listen_port,
                    ssl_cert=ssl_cert, ssl_key=ssl_key, ssl_keypass=args.ssl_keypass, ssl_ca_certs=ssl_ca_certs,
                    session_domain=args.session_domain, session_path=args.session_path,
                    session_secure=args.session_secure, session_timeout=args.session_timeout, outputs_key=args.outputs_key,
                    guvicorn_workers=args.guvicorn_workers, guvicorn_timeout=args.guvicorn_timeout,
                    agent_runner=agent_runner, mcp=mcp, mcp_listen_port=args.mcp_listen_port, mcp_ssl_listen_port=args.mcp_ssl_listen_port)

            msg = {"success":"web complate."}
            common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
            return 0, msg, w
        except Exception as e:
            msg = {"warn":f"Web server start error. {traceback.format_exc()}"}
            common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
            return 1, msg, w
