import os
import sys

import requests


class FolkAPI:
    BASE_URL = "https://api.folk.app/v1"

    def __init__(self, api_key: str):
        self.headers = {"Authorization": f"Bearer {api_key}"}

    def get_groups(self):
        """Fetch all groups from Folk."""
        url = f"{self.BASE_URL}/groups"
        response = requests.get(url, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def create_company(
        self,
        name: str,
        group_id: str = None,
        website: str = None,
        linkedin_url: str = None,
        description: str = None,
        emails=None,
        phones=None,
        addresses=None,
        urls=None,
        custom_field_values=None,
        groups=None,
        **kwargs,
    ):
        """Create a company (investor) in a specific group.

        This method builds a payload matching Folk's Create Company API:
        https://developer.folk.app/api-reference/companies/create-a-company

        It keeps backward compatibility with the previous `group_id`,
        `website` and `linkedin_url` arguments.
        """
        url = f"{self.BASE_URL}/companies"

        # Build the top-level payload expected by Folk
        data = {"name": name}
        if description:
            data["description"] = description

        # Groups: prefer explicit `groups`, else fall back to `group_id`
        if groups:
            # Accept either list of ids or list of dicts
            formatted = []
            for g in groups:
                if isinstance(g, dict) and g.get("id"):
                    formatted.append({"id": g["id"]})
                else:
                    formatted.append({"id": str(g)})
            data["groups"] = formatted
        elif group_id:
            data["groups"] = [{"id": group_id}]

        # Helper to normalize single or multiple inputs into lists
        def _to_list(val):
            if val is None:
                return None
            if isinstance(val, (list, tuple)):
                return [v for v in val if v is not None]
            return [val]

        # URLs: include website and linkedin_url if provided and merge with urls
        urls_list = _to_list(urls) or []
        if website:
            urls_list.append(website)
        if linkedin_url:
            urls_list.append(linkedin_url)
        if urls_list:
            data["urls"] = urls_list

        # Emails/phones/addresses
        emails_list = _to_list(emails)
        if emails_list:
            data["emails"] = emails_list
        phones_list = _to_list(phones)
        if phones_list:
            data["phones"] = phones_list
        addresses_list = _to_list(addresses)
        if addresses_list:
            data["addresses"] = addresses_list

        # Custom field values follow the API's structure
        if custom_field_values:
            data["customFieldValues"] = custom_field_values

        # Allow passing any additional top-level fields via kwargs (careful)
        for k, v in kwargs.items():
            # don't overwrite keys we explicitly set
            if k not in data:
                data[k] = v

        response = requests.post(url, headers=self.headers, json=data)
        response.raise_for_status()
        return response.json()

    def create_person(
        self,
        first_name: str,
        last_name: str,
        email: str = None,
        company_id: str = None,
        group_id: str = None,
        companies=None,
        emails=None,
        phones=None,
        addresses=None,
        urls=None,
        custom_field_values=None,
        groups=None,
        **kwargs,
    ):
        """Create a person in the workspace.

        Builds payload matching Folk's Create Person API: use camelCase
        keys (firstName, lastName, groups, companies, emails, etc.).
        Keeps backward compatibility with `company_id` and `group_id`.
        """
        url = f"{self.BASE_URL}/people"

        data = {"firstName": first_name, "lastName": last_name}

        # Groups: explicit `groups` preferred, else fallback to `group_id`
        if groups:
            formatted = []
            for g in groups:
                if isinstance(g, dict) and g.get("id"):
                    formatted.append({"id": g["id"]})
                else:
                    formatted.append({"id": str(g)})
            data["groups"] = formatted
        elif group_id:
            data["groups"] = [{"id": group_id}]

        # Companies: keep backward compatibility with company_id
        if companies:
            formatted = []
            for c in companies:
                if isinstance(c, dict):
                    formatted.append(c)
                elif isinstance(c, str):
                    # treat as id
                    formatted.append({"id": c})
            if formatted:
                data["companies"] = formatted
        elif company_id:
            data["companies"] = [{"id": company_id}]

        # Helper to normalize into lists
        def _to_list(val):
            if val is None:
                return None
            if isinstance(val, (list, tuple)):
                return [v for v in val if v is not None]
            return [val]

        emails_list = _to_list(emails) or []
        if email:
            emails_list.insert(0, email)
        if emails_list:
            data["emails"] = emails_list

        phones_list = _to_list(phones)
        if phones_list:
            data["phones"] = phones_list
        addresses_list = _to_list(addresses)
        if addresses_list:
            data["addresses"] = addresses_list
        urls_list = _to_list(urls)
        if urls_list:
            data["urls"] = urls_list

        if custom_field_values:
            data["customFieldValues"] = custom_field_values

        # Allow passthrough of other top-level fields in kwargs
        for k, v in kwargs.items():
            if k not in data:
                data[k] = v

        response = requests.post(url, headers=self.headers, json=data)
        response.raise_for_status()
        return response.json()


# Prefer getting the API key from the environment. If not set, fall back to the
# existing (hard-coded) key so behavior is unchanged for now.
DEFAULT_API_KEY = "FOLKfIGXuv74ML9EAajxyiUR39ePaNrZ"
api_key = os.environ.get("FOLK_API_KEY", DEFAULT_API_KEY)

folk = FolkAPI(api_key=api_key)


def example_flow():
    # Step 1: Get groups
    groups = folk.get_groups()
    print(groups)

    # Safely dig into the returned structure. The API returns groups under
    # groups['data']['items'] (not groups['data'][0]). Handle missing/empty.
    items = groups.get("data", {}).get("items", [])
    if not items:
        print("No groups returned by Folk API.")
        sys.exit(1)

    # Choose the first group as an example
    group_id = items[0].get("id")
    if not group_id:
        print("No id found for the first group item.")
        sys.exit(1)

    # Step 2: Choose a group_id and create a company
    company = folk.create_company(
        name="2050 Investment Partners",
        group_id=group_id,
        website="https://2050.com",
        linkedin_url="https://linkedin.com/company/2050-investments",
    )

    # Step 3: Add a person to the same group or company
    person = folk.create_person(
        first_name="John",
        last_name="Doe",
        email="john@2050.com",
        company_id=company.get("data", {}).get("id"),
        group_id=group_id,
    )

    print("Created company:", company)
    print("Created person:", person)


if __name__ == "__main__":
    try:
        example_flow()
    except requests.HTTPError as e:
        # Try to include response body for easier debugging if available
        resp = getattr(e, "response", None)
        if resp is not None:
            try:
                body = resp.text
            except Exception:
                body = "<unreadable response body>"
            print("HTTP error while talking to Folk API:", e)
            print("Response status:", resp.status_code)
            print("Response body:", body)
        else:
            print("HTTP error while talking to Folk API:", e)
        sys.exit(1)
    except Exception as e:  # pragma: no cover - top-level safety
        print("Unexpected error:", e)
        sys.exit(1)
