"""Generate an evidence-backed Company 360 brief from the Dealroom API.

Install:
    pip install authlib requests python-dotenv

Run:
    Create a .env file with DEALROOM_CLIENT_ID and DEALROOM_CLIENT_SECRET.
    python company_360_brief.py
    python company_360_brief.py --company YOUR_COMPANY_UUID
    python company_360_brief.py --json
"""

import argparse
import json
import os
import time
from datetime import date

from authlib.integrations.requests_client import OAuth2Session
from dotenv import load_dotenv

load_dotenv()

API_BASE = os.environ.get("DEALROOM_API_BASE", "https://api.beta.dealroom.app")
AUTH_URL = os.environ.get(
    "DEALROOM_AUTH_URL", "https://accounts.beta.dealroom.co/oauth/token"
)
AUDIENCE = os.environ.get(
    "DEALROOM_AUDIENCE", "https://api-next.beta.dealroom.co"
)
USER_AGENT = os.environ.get(
    "DEALROOM_USER_AGENT", "dealroom-cookbook-company-360/1.0"
)
DEFAULT_COMPANY_ID = "a3741a91-cbe8-4a50-9dba-69b4ee612973"  # Cerrion


class DealroomClient:
    """OAuth2 client with token refresh and bounded retry behavior."""

    def __init__(self):
        client_id = os.environ["DEALROOM_CLIENT_ID"]
        client_secret = os.environ["DEALROOM_CLIENT_SECRET"]
        self.session = OAuth2Session(
            client_id=client_id,
            client_secret=client_secret,
            token_endpoint=AUTH_URL,
        )
        self.session.headers.update(
            {"X-Client-Id": client_id, "User-Agent": USER_AGENT}
        )
        self._fetch_token()

    def _fetch_token(self):
        self.session.fetch_token(
            url=AUTH_URL,
            grant_type="client_credentials",
            audience=AUDIENCE,
        )

    def get(self, path, params=None):
        for attempt in range(5):
            response = self.session.get(f"{API_BASE}{path}", params=params)
            if response.status_code == 401 and attempt == 0:
                self._fetch_token()
                continue
            if response.status_code == 429 or response.status_code >= 500:
                if attempt == 4:
                    response.raise_for_status()
                retry_after = response.headers.get("Retry-After")
                try:
                    delay = float(retry_after) if retry_after else min(2**attempt, 8)
                except ValueError:
                    delay = min(2**attempt, 8)
                time.sleep(delay)
                continue
            response.raise_for_status()
            return response.json()
        raise RuntimeError(f"Dealroom request failed after retries: {path}")


def rows(payload):
    value = payload.get("data", [])
    return value if isinstance(value, list) else []


def month_key(row):
    return int(row.get("year") or 0) * 12 + int(row.get("month") or 0)


def month_label(row):
    year = row.get("year")
    if not year:
        return "date unavailable"
    month = row.get("month") or 1
    return date(int(year), int(month), 1).strftime("%b %Y")


def money(value):
    if value is None or value == 0:
        return "not disclosed"
    if abs(value) >= 1_000_000_000:
        return f"${value / 1_000_000_000:.1f}B"
    if abs(value) >= 1_000_000:
        return f"${value / 1_000_000:.1f}M"
    if abs(value) >= 1_000:
        return f"${value / 1_000:.0f}K"
    return f"${value:,.0f}"


def percent(value):
    return "not available" if value is None else f"{value:+.1f}%"


def fetch_brief(client, company_id):
    root = f"/data/companies/{company_id}"
    company = client.get(f"/data/entities/{company_id}", {"currency": "USD"})[
        "data"
    ]
    if company.get("organization_subtype") != "company":
        raise ValueError(f"{company_id} resolves to a non-company entity")

    funding = rows(client.get(f"{root}/funding-rounds", {"limit": 100}))
    valuations = rows(client.get(f"{root}/valuations", {"limit": 100}))
    investors = rows(
        client.get(f"{root}/investors", {"limit": 100, "include_total": "true"})
    )
    financials = rows(client.get(f"{root}/financials", {"currency": "USD"}))
    traffic = rows(client.get(f"{root}/web-traffic"))
    headcount = rows(client.get(f"{root}/headcount-breakdown"))
    team = rows(
        client.get(
            f"{root}/team",
            {"limit": 100, "include_total": "true", "is_past": "false"},
        )
    )

    funding.sort(key=month_key, reverse=True)
    valuations.sort(key=month_key, reverse=True)
    financials.sort(key=lambda row: int(row.get("year") or 0), reverse=True)
    traffic.sort(key=month_key)
    latest_traffic = traffic[-1] if traffic else None
    prior_traffic = traffic[-13] if len(traffic) > 12 else (traffic[0] if traffic else None)
    traffic_growth = None
    if latest_traffic and prior_traffic and (prior_traffic.get("visits") or 0) > 0:
        traffic_growth = (
            (latest_traffic["visits"] - prior_traffic["visits"])
            / prior_traffic["visits"]
            * 100
        )

    latest_breakdown = {}
    for kind in ("country", "department"):
        matching = [row for row in headcount if row.get("breakdown_type") == kind]
        latest_month = max((month_key(row) for row in matching), default=0)
        latest_breakdown[kind] = sorted(
            (row for row in matching if month_key(row) == latest_month),
            key=lambda row: row.get("percentage") or 0,
            reverse=True,
        )

    return {
        "generated_at": date.today().isoformat(),
        "currency": "USD",
        "company": company,
        "funding_rounds": funding,
        "valuations": valuations,
        "investors": investors,
        "financials": financials,
        "web_traffic": traffic,
        "web_traffic_change_12m_pct": traffic_growth,
        "headcount_breakdown": latest_breakdown,
        "team": team,
    }


def render_markdown(brief):
    company = brief["company"]
    company_data = company.get("company", {})
    funding_summary = company.get("funding_summary", {})
    funding = brief["funding_rounds"]
    valuations = brief["valuations"]
    investors = brief["investors"]
    team = brief["team"]
    financials = brief["financials"]
    traffic = brief["web_traffic"]
    latest_round = funding[0] if funding else None
    latest_financial = financials[0] if financials else None
    latest_valuation = valuations[0] if valuations else None

    lines = [
        f'# Company 360: {company["name"]}',
        "",
        f'> {company.get("tagline") or "No tagline available."}',
        "",
        "## Snapshot",
        "",
        f'- Headquarters: {company.get("hq_city") or "Unknown"}, {company.get("hq_country") or "Unknown"}',
        f'- Founded: {company.get("launch_year") or "Unknown"}',
        f'- Employees: {company.get("employee_count") or "Not available"} ({percent(company.get("employee_count_1y_growth"))} over one year)',
        f'- Signal rating: {company_data.get("signal_rating") or "Not available"}',
        f'- Total funding: {money(funding_summary.get("total_funding"))} across {funding_summary.get("round_count") or len(funding)} recorded rounds',
        f'- Latest valuation: {money(latest_valuation.get("value")) if latest_valuation else "not available"}',
        f'- Hiring: {company_data.get("open_jobs_count", 0)} active openings',
        "",
        "## Funding and investors",
        "",
    ]

    if latest_round:
        lead_names = [
            item.get("name")
            for item in latest_round.get("investors", [])
            if item.get("is_lead") and item.get("name")
        ]
        lines.extend(
            [
                f'- Latest round: {latest_round.get("standardized_round") or latest_round.get("round_type") or "Funding"}, {money(latest_round.get("amount"))}, {month_label(latest_round)}',
                f'- Latest-round leads: {", ".join(lead_names) or "not disclosed"}',
                f'- Known investors: {len(investors)}',
            ]
        )
    else:
        lines.append("- No funding rounds are recorded.")

    lines.extend(["", "### Funding history", ""])
    if funding:
        lines.extend(
            f'- {month_label(item)}: {item.get("standardized_round") or item.get("round_type") or "Funding"}, {money(item.get("amount"))}'
            for item in funding
        )
    else:
        lines.append("- No recorded rounds.")

    founders = [person for person in team if person.get("is_founder")]
    lines.extend(["", "## Team and traction", ""])
    lines.append(
        "- Founders: "
        + (
            "; ".join(
                f'{person["name"]} ({", ".join(person.get("titles") or []) or "Founder"})'
                for person in founders
            )
            or "not available"
        )
    )
    lines.append(f"- Current team members in Dealroom: {len(team)}")
    if latest_financial:
        lines.append(
            f'- Latest reported revenue: {money(latest_financial.get("revenue"))} ({latest_financial.get("year")})'
        )
    else:
        lines.append("- Latest reported revenue: not available")
    if traffic:
        lines.append(
            f'- Latest monthly web visits: {traffic[-1].get("visits", 0):,} ({month_label(traffic[-1])}), {percent(brief["web_traffic_change_12m_pct"])} over the comparison period'
        )
    else:
        lines.append("- Web traffic: not available")

    lines.extend(["", "## Diligence flags", ""])
    if financials and all(row.get("profit") is None for row in financials):
        lines.append("- Profit is not available in the company financial records.")
    if financials and all(row.get("rnd") is None for row in financials):
        lines.append("- R&D spend is not available in the company financial records.")
    estimated = [row for row in valuations if row.get("is_estimate")]
    if estimated:
        lines.append(
            f"- {len(estimated)} of {len(valuations)} recorded valuations are estimates."
        )
    lines.extend(
        [
            "- Web traffic is an estimate, not company-reported usage.",
            "- Shareholder ownership percentages and cap-table data are not exposed.",
            "",
            "## Sources",
            "",
            f'- [Dealroom company profile]({company.get("dealroom_url")})',
        ]
    )
    if latest_round and latest_round.get("source_url"):
        lines.append(f'- [Latest funding source]({latest_round["source_url"]})')
    lines.extend(
        [
            "",
            "This brief is a starting point for diligence, not an investment recommendation.",
        ]
    )
    return "\n".join(lines)


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        "--company",
        default=os.environ.get("DEALROOM_COMPANY_ID", DEFAULT_COMPANY_ID),
        help="Dealroom company UUID. Defaults to Cerrion from Cookbook 01.",
    )
    parser.add_argument(
        "--json", action="store_true", help="Print the source evidence as JSON."
    )
    args = parser.parse_args()

    brief = fetch_brief(DealroomClient(), args.company)
    print(json.dumps(brief, indent=2) if args.json else render_markdown(brief))


if __name__ == "__main__":
    main()
