import argparse
import json
import re
import shlex
import string
from urllib.parse import unquote

import rich
from rich.syntax import Syntax


def parse_curl_cmd(curl_cmd):
    parser = argparse.ArgumentParser()
    parser.add_argument('command')
    parser.add_argument('url')
    parser.add_argument('-d', '--data', '--data-binary', '--data-raw', '--data-ascii', "--data-urlencode")
    parser.add_argument('-H', '--header', action='append', default=[])
    args, _ = parser.parse_known_args(shlex.split(curl_cmd.replace(" $", " ")))
    method = "post" if args.data else "get"
    p = args.url.find("?")
    if p >= 0:
        url, query = args.url[:p], args.url[p + 1:]
    else:
        url, query = args.url, ""

    params = dict(re.findall(r'([^=&]+)=([^=&]*)', unquote(query)))
    headers = {}
    cookie_str = ""
    for header in args.header:
        k, v = map(str.strip, header.split(': ', 1))
        if k.lower() == "cookie":
            cookie_str = v
        else:
            headers[k] = v
    cookies = dict(re.findall(r'([^=\s;]+)=([^=;]*)', cookie_str))
    content_type = headers.get('Content-Type') or headers.get('content-type') or headers.get('Content-type')

    if args.data:
        if "application/json" in content_type.lower():
            data = json.loads(args.data)
        elif "application/x-www-form-urlencoded" in content_type.lower():
            data = dict(re.findall(r'([^=&]+)=([^=&]*)', unquote(args.data)))
    else:
        data = {}

    return dict(
        url=url,
        params=params,
        headers=headers,
        method=method,
        cookies=cookies,
        content_type=content_type,
        data=data
    )


py_template = """#######################################
#      The generated by curl2py.      
#      author：小小明                  
#######################################

import requests
import json

$headers
$cookies
$params
$data
res = requests.${method}(
    "${url}",
${param_list}
)
print(res.text)"""


def curlCmdGenPyScript(curl_cmd):
    context = parse_curl_cmd(curl_cmd)
    s = string.Template(template=py_template)
    param_list = []
    for name in ['params', 'headers', 'cookies', 'data']:
        if not context[name]:
            context[name] = ""
            continue
        tmp = json.dumps(context[name], ensure_ascii=False, indent=4)
        tmp = re.sub(r"(?m)(true|false),?$", lambda m: m.group(0).title(), tmp)
        tmp = f"{name} = {tmp}"
        context[name] = tmp
        if name == "data" and "application/json" in context["content_type"]:
            value = f"json.dumps({name}, ensure_ascii=False, separators=(',', ':'))"
            param_list.append(f"    {name}={value}")
        else:
            param_list.append(f"    {name}={name}")
    context["param_list"] = ",\n".join(param_list)
    return s.substitute(context)


def colorPrintPyCode(code: str):
    syntax = Syntax(code, "python", theme="material", line_numbers=True)
    rich.print(syntax)
