import os
import sys

import argparse
import stripe
from collections import defaultdict, deque
import re
import logging
from dataclasses import dataclass, field, asdict

import os
from dotenv import load_dotenv
import json
import asyncio

from tqdm import tqdm
from datetime import datetime, timedelta
import time

import json
from urllib.parse import urlparse
from urllib.parse import quote_plus


load_dotenv(dotenv_path=".env")  # idk if required

working_dir = os.getcwd()

project_root = os.path.abspath(
    os.path.join(os.path.dirname(__file__), "../../studio_api")
)
os.chdir(project_root)
sys.path.append(project_root)

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "studio_api.settings")
os.environ[
    "DJANGO_ALLOW_ASYNC_UNSAFE"
] = "true"  # https://docs.djangoproject.com/en/4.1/topics/async/#async-safety

database_url = f"postgresql://{os.getenv('DATABASE_USER')}:{quote_plus(os.getenv('DATABASE_PASSWORD'))}@{os.getenv('DATABASE_HOST')}/{os.getenv('DATABASE_NAME')}"
replica_database_url = database_url

print("Using database:")
print(f"- host: {os.getenv('DATABASE_HOST')}")
print(f"- username: {os.getenv('DATABASE_USER')}")
print(
    f"- password: {'*' * len(os.getenv('DATABASE_PASSWORD')) if os.getenv('DATABASE_PASSWORD') else 'None'}"
)
print(f"- database: {os.getenv('DATABASE_NAME')}")

if not database_url or not replica_database_url:
    raise ValueError(
        "DATABASE_URL and REPLICA_DATABASE_URL must be set in environment variables"
    )

os.environ["DATABASE_URL"] = database_url
os.environ["REPLICA_DATABASE_URL"] = replica_database_url

import django

django.setup()

from django.contrib.auth.models import Group, User
from studio_api.bots import models
from django.utils import timezone
from django.db.models import F


def load_file(file_path):
    with open(file_path, "r") as file:
        return [s.strip() for s in file.readlines()]


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Unjail users from botjail, maybe")
    parser.add_argument(
        "--user-id-file",
        type=str,
        required=True,
        help="Path to file containing user IDs (one per line)",
    )
    # parser.add_argument(
    #     "--copycat-name",
    #     type=str,
    #     required=True,
    #     help="Name of the copycat app/bot to store in the DB for reference.",
    # )
    parser.add_argument(
        "--execute",
        action="store_true",
        help="Actually execute changes. Without this flag, runs in dry-run mode",
    )

    args = parser.parse_args()

    should_execute = args.execute

    # combine working directory with user id file path using os.path.join
    user_id_file_path = os.path.join(working_dir, args.user_id_file)

    # load user ids
    user_ids = load_file(user_id_file_path)
    user_ids = [int(user_id) for user_id in user_ids]

    print(f"Loaded {len(user_ids)} user ids from {user_id_file_path}")

    BATCH_SIZE = 200

    total_batches = len(user_ids) // BATCH_SIZE + 1

    total_updated = 0
    total_new = 0

    # prompt for user confirmation if we are actually executing
    if should_execute:
        user_input = input(
            f"Are you sure you want to unjail up to {len(user_ids)} users from botjail? (y/n): "
        )
        if user_input.lower() != "y":
            print("Aborting.")
            exit(0)

    total_unjailed = 0

    for i in range(0, len(user_ids), BATCH_SIZE):
        batch_user_ids = user_ids[i : i + BATCH_SIZE]
        batch_number = i // BATCH_SIZE + 1
        print(f"Processing batch {batch_number} of {total_batches}")

        existing_botjailed_users = models.BotJail.objects.filter(
            user_id__in=batch_user_ids
        )

        if len(existing_botjailed_users) > BATCH_SIZE:
            raise Exception(
                f"Found {len(existing_botjailed_users)} botjailed users, more than expected. This should not happen."
            )

        """
            logic:
            - look at existing user
            - if they have are jailed for reason copycat or for reason api, leave them
            - latest_api_violation_at is not null
            - 
            - if they are outlook or hotmail, leave them
            - otherwise if they are jailed only for reason hcaptcha...        
        """

        for user in existing_botjailed_users:
            if (
                user.latest_jailed_reason == models.BotJail.Reason.COPYCAT
                or user.latest_jailed_reason == models.BotJail.Reason.API
            ):
                continue

            if user.user.email.lower().endswith(
                "@outlook.com"
            ) or user.user.email.lower().endswith("@hotmail.com"):
                continue

            if user.latest_api_violation_at is not None:
                continue

            if user.latest_copycat_violation_at is not None:
                continue

            total_unjailed += 1

            # otherwise, unjail them
            if should_execute:
                # now = timezone.now()
                user.status = models.BotJail.Status.SUSPICIOUS
                user.latest_released_at = timezone.now()
                user.save()
                print(f"Unjailed user {user.user_id} - {user.user.username}")
                time.sleep(0.1)
            else:
                print(f"Would have unjailed user {user.user_id} - {user.user.username}")

    print(f"🎶🎶🎶🎶🎶📣🤖🤖🤖 Unjailed {total_unjailed} users. 🎶🎶🎶🎶🎶📣🤖🤖🤖")
