import sys
import json
import logging
import time
from datetime import timedelta
from urllib.parse import urljoin
import petl
from oaa.hooks.decorators import OAAHookEvent, hook
from oaa.oaa_utils import get_oaa_client
from oaaclient.client import OAAResponseError
from faker import Faker
logger = logging.getLogger(__name__)

fake = Faker()


@hook(event=OAAHookEvent.POST_TRANSFORM, target='users')
def hook_name(event, source=None, **kwargs):

    '''
    hook_name is a hook for doing some custom thing at this point in the flow.
    '''
    # for board_rec in sources['boards'].records:

    # import bpdb; bpdb.set_trace()  # noqa: E702

def wait_for_status_to_appear(datasource_id):
    """TODO: Docstring for wait_for_status_to_appear.
    :returns: TODO

    """
    veza_con = get_oaa_client()
    path = f'/api/v1/providers/datasources/{datasource_id}/parse_status'
    status_response = None
    done = False

    while not done:
        try:
            # logger.info('checking status at %s', path)
            status_response = veza_con.api_get(path)
            done = True
        except OAAResponseError as err:
            # logger.debug('datasource [%s] does not have a status yet', datasource_id)
            # logger.debug(err.details)
            time.sleep(1)

    # import tqdm
    # tqdm.tqdm([a for a in waiter()])

    return status_response

@hook(event=OAAHookEvent.POST_PUSH_OAA)
def hook_name(event, datasource_id, config=None, **kwargs):

    '''
    hook_name is a hook for doing some custom thing at this point in the flow.
    '''
    # for board_rec in sources['boards'].records:
    # /api/v1/providers/datasources/{id}/parse_status

    provider_id = ''
    status_response = wait_for_status_to_appear(datasource_id)
    integration_url = urljoin(str(config.VEZA_URL), f'/app/integrations/custom/{provider_id}?tab=data_sources')
    output = {
        'status': status_response,
        'integration_url': integration_url  
    }
    # json.dump(status, sys.stdout, indent=2)
    print(json.dumps(output, indent=2))


def fetch(connection=None, source=None, **kwargs):
    '''
    Fetch the data. This is the function that is called by oaa.

    '''

    gen_data = generate_data(source.params.get('USER_COUNT', 10))
    # res = write_csv(10)

    return petl.fromdicts(gen_data)


# --- Configuration ---

# Define specific departments to match the business context of your sample
departments = [
    "Human Resources", "Business Development", "Training", "Services", 
    "Research and Development", "IT", "Marketing", "Sales", "Executive", 
    "Legal", "Engineering", "Support"
]

def generate_data(ROW_COUNT=100):
    
    # Generate n=ROW_COUNT rows

    for i in range(ROW_COUNT):
        # 1. Generate Names
        first_name = fake.first_name()
        last_name = fake.last_name()
        full_name = f"{first_name} {last_name}"

        # 2. Generate Username 
        # Pattern: first initial + last name + unique index (starting at 10)
        # We strip special chars from last name just in case (e.g. O'Conner -> OConner)
        clean_last = "".join(filter(str.isalpha, last_name))
        username = f"{first_name[0].lower()}{clean_last.lower()}{i + 10}"

        # 3. Generate Email
        domain = fake.random_element(elements=("example.com", "example.io"))
        email = f"{username}@{domain}"

        # 4. Generate Dates
        # Created within the last 3 years
        created_at_dt = fake.date_time_between(start_date='-3y', end_date='-1y')

        # Last login must be after created_at
        # We add a random time delta to the created date
        days_after = fake.random_int(min=1, max=300)
        last_login_dt = created_at_dt + timedelta(days=days_after)

        # Format dates to ISO 8601 (e.g., 2021-04-08T08:58:54Z)
        created_at = created_at_dt.strftime("%Y-%m-%dT%H:%M:%SZ")
        last_login = last_login_dt.strftime("%Y-%m-%dT%H:%M:%SZ")

        # 5. Other fields

        user_dict = {
            "username": username,
            "email": email,
            "full_name": full_name,
            "created_at": created_at,
            "last_login": last_login,
            "is_active": fake.boolean(),
            "department": fake.random_element(elements=departments)
        }
        # rows.append([username, email, full_name, created_at, last_login, is_active, department])
        yield user_dict
