# Copyright (c) 2020 CloudZero - ALL RIGHTS RESERVED - PROPRIETARY AND CONFIDENTIAL
# Unauthorized copying of this file and/or project, via any medium is strictly prohibited.
# Direct all questions to legal@cloudzero.com
#

import datetime
import sys

from src.api.v4_autolink import (
    disable_connection_auto_link_v4,
    display_organization_auto_link_status,
    enable_connection_auto_link_v4,
    get_organization_auto_link_status_v4,
    update_connection_auto_link_ignore_list_v4,
)
from src.exceptions import CzOpsApiException
from src.utils.console import eprint


def _get_payer_accounts(organization_id: str, debug: bool = False) -> dict:
    """Get payer accounts for an organization using organization API."""
    from src.api.v4_organizations import get_organizations

    try:
        # Use the organization API which includes connections_summary
        orgs_data = get_organizations(organization_query=organization_id, debug=debug)

        if debug:
            eprint(f"DEBUG: Retrieved organization details for org {organization_id}")

        # Get the organization details (should be a dict with org_id as key)
        if organization_id in orgs_data:
            org_details = orgs_data[organization_id]

            # Get connections from connections_summary if available
            connections_summary = getattr(org_details, "connections_summary", {})
            connections = connections_summary.get("connections", {}) if isinstance(connections_summary, dict) else {}

            if debug:
                eprint(f"DEBUG: Found {len(connections)} connections in organization")

            # Filter for AWS payer accounts (COST type connections)
            payer_accounts = {}
            for conn_id, conn_data in connections.items():
                if isinstance(conn_data, dict):
                    provider = conn_data.get("provider", "")

                    # Check if this is a COST connection (payer account)
                    # The connection_id format is "ACCOUNT_ID#TYPE", so COST connections end with "#COST"
                    is_cost_connection = conn_id.endswith("#COST") if isinstance(conn_id, str) else False

                    if provider == "AWS" and is_cost_connection:
                        payer_accounts[conn_id] = conn_data
                        if debug:
                            conn_name = conn_data.get("connection_name", conn_id)
                            eprint(f"DEBUG: Found payer account: {conn_id} ({conn_name})")

            if debug:
                eprint(f"DEBUG: Found {len(payer_accounts)} AWS payer accounts")

            return payer_accounts
        else:
            if debug:
                eprint(f"DEBUG: Organization {organization_id} not found in response")
            return {}

    except Exception as e:
        eprint(f"ERROR: Cannot retrieve payer accounts from organization API: {e}")

        # Fallback: try auto-link status API
        if debug:
            eprint("DEBUG: Falling back to auto-link status API")

        try:
            from src.api.v4_autolink import get_organization_auto_link_status_v4

            auto_link_status = get_organization_auto_link_status_v4(organization_id)

            if debug:
                eprint(f"DEBUG: Retrieved auto-link status for org {organization_id}")

            # The auto-link status already identifies payer accounts
            payer_accounts = auto_link_status.auto_link_enabled_connections or {}
            disabled_accounts = auto_link_status.auto_link_disabled_connections or {}

            # Combine both - we want all payer accounts regardless of auto-link status
            all_payer_accounts = {**disabled_accounts, **payer_accounts}

            if debug:
                eprint(f"DEBUG: Found {len(all_payer_accounts)} payer accounts from auto-link status")

            return all_payer_accounts

        except Exception as autolink_error:
            if debug:
                eprint(f"DEBUG: Auto-link status API also failed: {autolink_error}")

            eprint("ERROR: Cannot retrieve payer accounts from any available API")
            return {}


def _get_auto_link_enabled_connections(organization_id: str) -> dict:
    """Get connections with auto-link enabled for an organization."""
    try:
        auto_link_status = get_organization_auto_link_status_v4(organization_id)
        return auto_link_status.auto_link_enabled_connections
    except CzOpsApiException as e:
        eprint(f"ERROR: Failed to get organization auto-link status: {e}")
        return {}


def enable_auto_link(organization_id: str, role_name: str, arguments: dict | None = None) -> bool:
    """Enable auto-link for payer accounts in an organization."""
    if not role_name:
        eprint("ERROR: You must provide a role name to use for auto-link")
        return False

    debug = arguments.get("--debug", False) if arguments else False

    # Get payer accounts for the organization
    payer_accounts = _get_payer_accounts(organization_id, debug=debug)

    if not payer_accounts:
        eprint(f"No AWS payer accounts found for organization {organization_id}")
        return False

    print(f"Enabling auto-link for organization {organization_id}")
    success_count = 0
    failed_accounts = []

    for connection_pk in payer_accounts:
        # Extract AWS account ID from connection PK (e.g., "095300923743#COST" -> "095300923743")
        aws_account_id = connection_pk.split("#")[0]

        try:
            print(f" - Configuring payer account {aws_account_id} to use auto-link role '{role_name}'")

            result = enable_connection_auto_link_v4(aws_account_id, role_name, force=False)

            if result.get("success") and result.get("auto_link_enabled"):
                print(f" - Auto-link enabled for {aws_account_id}")
                success_count += 1
            else:
                print(f" - Warning: {result}")
                failed_accounts.append(aws_account_id)

        except CzOpsApiException as error:
            eprint(f"ERROR: Enabling auto-link for {aws_account_id} failed: {error}")
            failed_accounts.append(aws_account_id)
        except Exception as error:
            eprint(f"ERROR: Unexpected error enabling auto-link for {aws_account_id}: {error}")
            failed_accounts.append(aws_account_id)

    # Report results
    if success_count > 0:
        next_hour = (datetime.datetime.now() + datetime.timedelta(hours=1)).astimezone().strftime("%H:00 %Z")
        print(
            f"\nAuto-link enabled for {success_count}/{len(payer_accounts)} accounts in organization {organization_id}"
        )
        print(f"Next auto-link account discovery will run at {next_hour}")

        if failed_accounts:
            print(f"Failed accounts: {', '.join(failed_accounts)}")

        return True
    else:
        eprint(f"Failed to enable auto-link for any accounts in organization {organization_id}")
        return False


def disable_auto_link(organization_id: str, arguments: dict | None = None) -> bool:
    """Disable auto-link for all enabled accounts in an organization."""
    auto_link_accounts = _get_auto_link_enabled_connections(organization_id)

    if not auto_link_accounts:
        eprint(f"No auto-link enabled accounts found for organization {organization_id}")
        return False

    print(f"Disabling auto-link for organization {organization_id}")
    success_count = 0
    failed_accounts = []

    for connection_pk in auto_link_accounts:
        # Extract AWS account ID from connection PK (e.g., "095300923743#COST" -> "095300923743")
        aws_account_id = connection_pk.split("#")[0]

        try:
            print(f" - Disabling auto-link on account {aws_account_id}")

            result = disable_connection_auto_link_v4(aws_account_id, force=False)

            if result.get("success") and result.get("auto_link_enabled"):
                print(f" - Auto-link disabled for {aws_account_id}")
                success_count += 1
            else:
                print(f" - Warning: {result.get('message')}")
                failed_accounts.append(aws_account_id)

        except CzOpsApiException as error:
            eprint(f"ERROR: Disabling auto-link for {aws_account_id} failed: {error}")
            failed_accounts.append(aws_account_id)
        except Exception as error:
            eprint(f"ERROR: Unexpected error disabling auto-link for {aws_account_id}: {error}")
            failed_accounts.append(aws_account_id)

    # Report results
    if success_count > 0:
        print(
            f"\nAuto-link disabled for {success_count}/{len(auto_link_accounts)} accounts in organization {organization_id}"
        )

        if failed_accounts:
            print(f"Failed accounts: {', '.join(failed_accounts)}")

        return True
    else:
        eprint(f"Failed to disable auto-link for any accounts in organization {organization_id}")
        return False


def status_auto_link(organization_id: str, arguments: dict | None = None) -> bool:
    """Get the auto-link status for an organization."""
    debug = arguments.get("--debug", False) if arguments else False

    try:
        auto_link_status = get_organization_auto_link_status_v4(organization_id, debug=debug)
        print(display_organization_auto_link_status(auto_link_status))
        return True
    except CzOpsApiException as e:
        eprint(f"ERROR: Failed to get auto-link status: {e}")
        return False


def ignore_auto_link(organization_id: str, ignore_list: str, arguments: dict | None = None) -> bool:
    """Add AWS account IDs to the auto-link ignore list."""
    if not ignore_list:
        eprint("ERROR: No ignore list provided. Please specify accounts to ignore with --ignore-list")
        return False

    # Parse the ignore list from comma-separated string to list
    parsed_ignore_list = [acc.strip() for acc in ignore_list.replace("'", "").split(",") if acc.strip()]

    if not parsed_ignore_list:
        eprint("ERROR: No valid account IDs found in ignore list")
        return False

    auto_link_accounts = _get_auto_link_enabled_connections(organization_id)

    if not auto_link_accounts:
        eprint(f"No auto-link enabled accounts found for organization {organization_id}")
        return False

    print(f"Adding the following accounts to the auto-link ignore list for organization {organization_id}:")
    for account_id in sorted(parsed_ignore_list):
        print(f"  {account_id}")
    print("")

    success_count = 0
    failed_accounts = []

    for connection_pk in auto_link_accounts:
        # Extract AWS account ID from connection PK (e.g., "095300923743#COST" -> "095300923743")
        aws_account_id = connection_pk.split("#")[0]

        try:
            print(f" - Updating ignore list for account {aws_account_id}")

            result = update_connection_auto_link_ignore_list_v4(aws_account_id, parsed_ignore_list, action="add")

            if result.get("success"):
                print(f" - Successfully updated ignore list for {aws_account_id}")
                success_count += 1
            else:
                print(f" - Warning: {result.get('message')}")
                failed_accounts.append(aws_account_id)

        except CzOpsApiException as error:
            eprint(f"ERROR: Updating ignore list for {aws_account_id} failed: {error}")
            failed_accounts.append(aws_account_id)
        except Exception as error:
            eprint(f"ERROR: Unexpected error updating ignore list for {aws_account_id}: {error}")
            failed_accounts.append(aws_account_id)

    # Report results
    if success_count > 0:
        print(
            f"\nAuto-link ignore list updated for {success_count}/{len(auto_link_accounts)} accounts in organization {organization_id}"
        )

        if failed_accounts:
            print(f"Failed accounts: {', '.join(failed_accounts)}")

        return True
    else:
        eprint(f"Failed to update auto-link ignore list for any accounts in organization {organization_id}")
        return False


def functions(arguments, organization_data):
    """Entry point for auto-link commands, passing through arguments from CLI."""
    for cz_organization_id, _details in organization_data.items():
        if arguments["enable"]:
            result = enable_auto_link(cz_organization_id, arguments["<ROLE-NAME>"], arguments)
        elif arguments["disable"]:
            result = disable_auto_link(cz_organization_id, arguments)
        elif arguments["status"]:
            result = status_auto_link(cz_organization_id, arguments)
        elif arguments["ignore"]:
            result = ignore_auto_link(cz_organization_id, arguments["--ignore-list"], arguments)
        else:
            eprint("Unsupported")
            sys.exit(-1)

        return result
    return None
