from concurrent.futures import ThreadPoolExecutor
from dataclasses import dataclass, field
from time import time

import pandas as pd
from dacite import from_dict

from gandai import query, models, gpt
from gandai.sources import GrataWrapper as grata
from gandai.sources import GoogleMapsWrapper as google


def enrich_company_by_domain(domain: str) -> None:
    company = query.find_company_by_domain(domain)
    if "company_uid" not in company.meta.keys():
        # company_uid is a grata specific field
        resp = grata.enrich(domain)
        # print(resp)
        # what happens when company is not found?
        # -> {'status': 404, 'errors': [{'field': 'domain', 'message': 'Cannot associate domain asdfasdf.com with a company.'}], 'linkedin': None, 'ownership': None}
        company.name = company.name or resp.get("name")
        company.description = resp.get("description")
        company.meta = {**company.meta, **resp}
        query.update_company(company)


def run_similarity_search(search: models.Search, domain: str) -> None:
    # dealcloud_companies = 
    grata_companies = grata.find_similar(domain=domain, search=search)
    query.insert_companies_as_targets(
        companies=grata_companies, search_uid=search.uid, actor_key="grata"
    )

def run_criteria_search(search: models.Search) -> None:
    grata_companies = grata.find_by_criteria(search)
    query.insert_companies_as_targets(
        companies=grata_companies, search_uid=search.uid, actor_key="grata"
    )

def run_maps_search(search: models.Search, event: models.Event) -> None:
    print("running maps search... may take 30++ seconds")
    start = time()
    top_n = event.data.get("top_n", 1)
    radius_miles = event.data.get("radius", 10)

    def process_area(area: str) -> None:
        centroids = gpt.get_top_zip_codes(area=area, top_n=top_n)
        print(f"searching {area} with {len(centroids)} centroids: {centroids}")

        place_ids = google.fetch_unique_place_ids(
            search_phrase=event.data["phrase"],
            locations=centroids,
            radius_miles=radius_miles,
        )
        print(f"{len(place_ids)} place_ids found in {area}")
        
        with ThreadPoolExecutor(max_workers=10) as executor:
            for place_id in place_ids:
                executor.submit(
                    google.build_target_from_place_id,
                    place_id=place_id,
                    search_uid=search.uid,
                    append_to_prompt=event.data['prompt']
                )

    # with ThreadPoolExecutor(max_workers=5) as executor:
    #     executor.map(process_area, e.data["areas"])
    for area in event.data["areas"]:
        process_area(area)


    print(f"🗺  Maps took {time() - start} seconds")

def process_event(event_id: int) -> None:
    event: models.Event = query.find_event_by_id(event_id)
    search = query.find_search(uid=event.search_uid)
    domain = event.domain
    if event.type == "create":
        # gpt enrich here
        pass
    elif event.type == "advance":
        enrich_company_by_domain(domain=domain) # 1 grata credit
    elif event.type == "validate":
        enrich_company_by_domain(domain=domain)
        run_similarity_search(search=search, domain=domain)
    elif event.type == "send":
        pass
    elif event.type == "client_approve":
        pass
    elif event.type == "reject":
        pass
    elif event.type == "client_reject":
        pass
    elif event.type == "conflict":
        enrich_company_by_domain(domain=domain)
        run_similarity_search(search=search, domain=domain)
    elif event.type == "client_conflict":
        enrich_company_by_domain(domain=domain)
        run_similarity_search(search=search, domain=domain)
    elif event.type == "criteria":
        if len(event.data['inclusion']["keywords"]) > 0:
            run_criteria_search(search=search)

    elif event.type == "maps":
        run_maps_search(search=search, event=event)

    elif event.type == "import":
        data = event.data
        query.insert_targets_from_domains(
            domains=data["domains"],
            search_uid=event.search_uid,
            actor_key=event.actor_key,
            stage=data.get("stage", "advance"),
        )

    elif event.type == "reset":
        print("💣 Resetting Inbox...")
        query.reset_inbox(search_uid=search.uid)

    