"""Generate config flow file."""
import json
from typing import Dict

from .model import Config, Integration

BASE = """
\"\"\"Automatically generated by hassfest.

To update, run python3 -m script.hassfest
\"\"\"

# fmt: off

FLOWS = {}
""".strip()


def validate_integration(integration: Integration):
    """Validate we can load config flow without installing requirements."""
    if not (integration.path / "config_flow.py").is_file():
        integration.add_error(
            "config_flow", "Config flows need to be defined in the file config_flow.py"
        )

    # Currently not require being able to load config flow without
    # installing requirements.
    # try:
    #     integration.import_pkg('config_flow')
    # except ImportError as err:
    #     integration.add_error(
    #         'config_flow',
    #         "Unable to import config flow: {}. Config flows should be able "
    #         "to be imported without installing requirements.".format(err))
    #     return

    # if integration.domain not in config_entries.HANDLERS:
    #     integration.add_error(
    #         'config_flow',
    #         "Importing the config flow platform did not register a config "
    #         "flow handler.")


def generate_and_validate(integrations: Dict[str, Integration]):
    """Validate and generate config flow data."""
    domains = []

    for domain in sorted(integrations):
        integration = integrations[domain]

        if not integration.manifest:
            continue

        config_flow = integration.manifest.get("config_flow")

        if not config_flow:
            continue

        validate_integration(integration)

        domains.append(domain)

    return BASE.format(json.dumps(domains, indent=4))


def validate(integrations: Dict[str, Integration], config: Config):
    """Validate config flow file."""
    config_flow_path = config.root / "homeassistant/generated/config_flows.py"
    config.cache["config_flow"] = content = generate_and_validate(integrations)

    if config.specific_integrations:
        return

    with open(str(config_flow_path)) as fp:
        if fp.read().strip() != content:
            config.add_error(
                "config_flow",
                "File config_flows.py is not up to date. "
                "Run python3 -m script.hassfest",
                fixable=True,
            )
        return


def generate(integrations: Dict[str, Integration], config: Config):
    """Generate config flow file."""
    config_flow_path = config.root / "homeassistant/generated/config_flows.py"
    with open(str(config_flow_path), "w") as fp:
        fp.write(f"{config.cache['config_flow']}\n")

@@ -63,16 +63,79 @@
 t Dict%0A%0A
+from homeassistant.requirements import DISCOVERY_INTEGRATIONS%0A%0A
 from .mo
@@ -307,16 +307,82 @@
 trip()%0A%0A
+UNIQUE_ID_IGNORE = %7B%22esphome%22, %22fritzbox%22, %22heos%22, %22huawei_lte%22%7D%0A%0A
 %0Adef val
@@ -391,32 +391,48 @@
 ate_integration(
+config: Config, 
 integration: Int
@@ -462,80 +462,65 @@
 ate 
-we can load config flow without installing requirements.%22%22%22%0A    if not (
+config flow of an integration.%22%22%22%0A    config_flow_file = 
 inte
@@ -550,17 +550,45 @@
 flow.py%22
-)
+%0A%0A    if not config_flow_file
 .is_file
@@ -724,127 +724,112 @@
   )%0A
-%0A
     
-# Currently not require being able to load config flow without%0A    # installing requirements.%0A    # try:
+    return%0A%0A    needs_unique_id = integration.domain not in UNIQUE_ID_IGNORE and any(
 %0A    
-#
     
+key in
  int
@@ -841,295 +841,450 @@
 ion.
-import_pkg('config_flow')%0A    # except ImportError as err:%0A
+manifest%0A        for keys in DISCOVERY_INTEGRATIONS.values()%0A 
     
-#
    
-  integration.add_error(
+for key in keys%0A    )%0A%0A    if not needs_unique_id:
 %0A    
-#
     
-     'config_flow',%0A    #         %22Unable to import
+return%0A%0A    config_flow = config_flow_file.read_text()%0A%0A    has_unique_id = (%0A        %22self.async_set_unique_id%22 in
  config
- 
+_
 flow
-: %7B%7D. Config flows should be able %22%0A    #         %22to be imported without installing requirements.%22.format(err))%0A    #
+%0A        or %22config_entry_flow.register_discovery_flow%22 in config_flow%0A        or %22config_entry_oauth2_flow.AbstractOAuth2FlowHandler%22 in config_flow%0A    )%0A%0A    if has_unique_id:%0A 
      
+  
 retu
@@ -1295,73 +1295,122 @@
     
-# if integration.domain not in config_entries.HANDLERS
+if config.specific_integrations:%0A        notice_method = integration.add_warning%0A    else
 :%0A    
-#
     
+notice_method =
  int
@@ -1431,24 +1431,37 @@
 rror
-(%0A    # 
+%0A%0A    notice_method(%0A
         
 'con
@@ -1456,17 +1456,17 @@
         
-'
+%22
 config_f
@@ -1472,118 +1472,76 @@
 flow
-',%0A    #         %22Importing the config flow platform did not register a config %22%0A    #         %22flow handler.%22
+%22, %22Config flows that are discoverable need to set a unique ID%22%0A    
 )%0A%0A%0A
@@ -1602,16 +1602,32 @@
 gration%5D
+, config: Config
 ):%0A    %22
@@ -1974,16 +1974,24 @@
 gration(
+config, 
 integrat
@@ -2346,16 +2346,24 @@
 grations
+, config
 )%0A%0A    i

Validate that discovered config flows set a unique ID (#34751)