import sys
from concurrent.futures import ThreadPoolExecutor, as_completed
from acquiscan import extract
from acquiscan.llm_client import LLMClient
from acquiscan.sec_client import SECClient
from acquiscan.scan_utils import (
    LLM_FORM_TYPES,
    create_result,
    filing_url
)

def get_filings_with_excerpts(sec_client, company_info, filings, silent):
    cik = company_info["cik"]
    result_filings = []
    for i, filing in enumerate(filings, 1):
        if not silent:
            print(f"[{i}/{len(filings)}] {filing['form']} ({filing['filingDate']})", file=sys.stderr)
        doc_html = sec_client.get_filing_document(
            cik, filing["accessionNumberClean"], filing["primaryDocument"]
        )
        if not doc_html:
            continue
        excerpts = extract.extract_acquisition_excerpts(doc_html)
        if not excerpts:
            if not silent:
                print("  No relevant excerpts", file=sys.stderr)
            continue
        if not silent:
            print(f"  {len(excerpts)} excerpt(s)", file=sys.stderr)
        result_filings.append({
            "form_type": filing["form"],
            "filing_date": filing["filingDate"],
            "url": filing_url(cik, filing),
            "excerpts": excerpts,
        })
    return result_filings

def get_filing_portfolio(llm_client, company_name, filing_data):
    try:
        acquisitions = llm_client.extract_acquisitions(
            filing_data["excerpts"], company_name, filing_data["form_type"]
        )
        portfolio = []
        for acq in (acquisitions or []):
            name = acq.get("company_name", "").strip()
            if name:
                portfolio.append({
                    "name": name,
                    "description": acq.get("description", ""),
                    "form_type": filing_data["form_type"],
                    "filing_date": filing_data["filing_date"],
                    "url": filing_data["url"],
                })
        return portfolio, None
    except Exception as e:
        return [], e

def _run_parallel_extraction(llm_client, company_name, result_filings, silent, workers=5):
    portfolio = {}
    total = len(result_filings)
    with ThreadPoolExecutor(max_workers=workers) as executor:
        futures = {executor.submit(get_filing_portfolio, llm_client, company_name, fd): fd for fd in result_filings}
        for i, future in enumerate(as_completed(futures), 1):
            filing_data = futures[future]
            filing_portfolio, error = future.result()
            label = f"[{i}/{total}] {filing_data['form_type']} ({filing_data['filing_date']})"
            if error:
                print(f"{label}: Error: {error}", file=sys.stderr)
            elif not silent:
                print(label, file=sys.stderr)
            filing_data["portfolio"] = filing_portfolio
            for entry in filing_portfolio:
                key = entry["name"].lower()
                existing = portfolio.get(key)
                if not existing or entry["filing_date"] > existing["filing_date"]:
                    portfolio[key] = entry
    return portfolio

def run_llm_scan(
    company_name, config, silent=False, from_date=None, to_date=None,
    include_excerpts=False, include_filings=False,
):
    sec_client = SECClient(config.user_agent)
    if not silent:
        print(f"Searching for company: {company_name}", file=sys.stderr)
    company_info = sec_client.search_company(company_name)
    if not company_info:
        print("Company not found", file=sys.stderr)
        return create_result({"name": company_name, "cik": None}, portfolio=[])
    if not silent:
        print(f"Found: {company_info['name']} (CIK: {company_info['cik']})", file=sys.stderr)
    filings = sec_client.get_company_filings(
        company_info["cik"], LLM_FORM_TYPES, from_date, to_date
    )
    if not filings:
        print("No filings found", file=sys.stderr)
        return create_result(company_info, portfolio=[])
    if not silent:
        print(f"Found {len(filings)} filing(s)", file=sys.stderr)

    try:
        llm_client = LLMClient(config)
    except ValueError as e:
        print(f"Error: LLM not available: {e}", file=sys.stderr)
        return create_result(company_info, portfolio=[])

    result_filings = get_filings_with_excerpts(sec_client, company_info, filings, silent)
    if not result_filings:
        print("No excerpts found in any filings", file=sys.stderr)
        return create_result(company_info, portfolio=[])

    if not silent:
        print("Extracting acquisitions with LLM...", file=sys.stderr)
    portfolio = _run_parallel_extraction(llm_client, company_info["name"], result_filings, silent)

    if not include_excerpts:
        for fd in result_filings:
            fd.pop("excerpts", None)

    portfolio_list = list(portfolio.values())
    if not silent:
        print(f"Found {len(portfolio_list)} companies", file=sys.stderr)

    result = create_result(company_info, portfolio=portfolio_list)
    if include_filings:
        result["filings"] = result_filings
    return result
