import type { Selector } from "../../data/selector";
import type { HaFormData, HaFormSchema } from "./types";

const setDefaultValue = (
  field: HaFormSchema,
  value: HaFormData | undefined
) => {
  if ("selector" in field && "choose" in field.selector) {
    const firstChoice = Object.keys(field.selector.choose.choices)[0];
    if (firstChoice) {
      return {
        active_choice: firstChoice,
        [firstChoice]: value,
      };
    }
  }
  return value;
};

export const computeInitialHaFormData = (
  schema: HaFormSchema[] | readonly HaFormSchema[]
): Record<string, any> => {
  const data = {};
  schema.forEach((field) => {
    if (
      field.description?.suggested_value !== undefined &&
      field.description?.suggested_value !== null
    ) {
      data[field.name] = setDefaultValue(
        field,
        field.description.suggested_value
      );
    } else if ("default" in field) {
      data[field.name] = setDefaultValue(field, field.default);
    } else if (field.type === "expandable") {
      const expandableData = computeInitialHaFormData(field.schema);
      if (field.required || Object.keys(expandableData).length) {
        // Only add expandable data if it's required or any of its children have initial values.
        data[field.name] = expandableData;
      }
    } else if (!field.required) {
      // Do nothing.
    } else if (field.type === "boolean") {
      data[field.name] = false;
    } else if (field.type === "string") {
      data[field.name] = "";
    } else if (field.type === "integer") {
      data[field.name] = "valueMin" in field ? field.valueMin : 0;
    } else if (field.type === "constant") {
      data[field.name] = field.value;
    } else if (field.type === "float") {
      data[field.name] = 0.0;
    } else if (field.type === "select") {
      if (field.options.length) {
        const val = field.options[0];
        data[field.name] = Array.isArray(val) ? val[0] : val;
      }
    } else if (field.type === "positive_time_period_dict") {
      data[field.name] = {
        hours: 0,
        minutes: 0,
        seconds: 0,
      };
    } else if ("selector" in field) {
      const selector: Selector = field.selector;

      if ("device" in selector) {
        data[field.name] = selector.device?.multiple ? [] : "";
      } else if ("entity" in selector) {
        data[field.name] = selector.entity?.multiple ? [] : "";
      } else if ("area" in selector) {
        data[field.name] = selector.area?.multiple ? [] : "";
      } else if ("label" in selector) {
        data[field.name] = selector.label?.multiple ? [] : "";
      } else if ("boolean" in selector) {
        data[field.name] = false;
      } else if (
        "addon" in selector ||
        "attribute" in selector ||
        "file" in selector ||
        "icon" in selector ||
        "serial_port" in selector ||
        "template" in selector ||
        "text" in selector ||
        "theme" in selector ||
        "object" in selector
      ) {
        data[field.name] = "";
      } else if ("number" in selector) {
        data[field.name] = selector.number?.min ?? 0;
      } else if ("select" in selector) {
        if (selector.select?.options.length) {
          const firstOption = selector.select.options[0];
          const val =
            typeof firstOption === "string" ? firstOption : firstOption.value;
          data[field.name] = selector.select.multiple ? [val] : val;
        }
      } else if ("country" in selector) {
        if (selector.country?.countries?.length) {
          data[field.name] = selector.country.countries[0];
        }
      } else if ("language" in selector) {
        if (selector.language?.languages?.length) {
          data[field.name] = selector.language.languages[0];
        }
      } else if ("duration" in selector) {
        data[field.name] = {
          hours: 0,
          minutes: 0,
          seconds: 0,
        };
      } else if ("time" in selector) {
        data[field.name] = "00:00:00";
      } else if ("date" in selector || "datetime" in selector) {
        const now = new Date().toISOString().slice(0, 10);
        data[field.name] = `${now}T00:00:00`;
      } else if ("color_rgb" in selector) {
        data[field.name] = [0, 0, 0];
      } else if ("color_temp" in selector) {
        data[field.name] = selector.color_temp?.min_mireds ?? 153;
      } else if (
        "action" in selector ||
        "trigger" in selector ||
        "condition" in selector
      ) {
        data[field.name] = [];
      } else if ("media" in selector || "target" in selector) {
        data[field.name] = {};
      } else if ("state" in selector) {
        data[field.name] = selector.state?.multiple ? [] : "";
      } else if ("choose" in selector) {
        const firstChoice = Object.keys(selector.choose.choices)[0];
        if (!firstChoice) {
          data[field.name] = {};
        } else {
          data[field.name] = {
            active_choice: firstChoice,
            [firstChoice]: computeInitialHaFormData([
              {
                name: firstChoice,
                selector: selector.choose.choices[firstChoice].selector,
              },
            ])[firstChoice],
          };
        }
      } else if ("numeric_threshold" in selector) {
        const mode = selector.numeric_threshold?.mode ?? "crossed";
        const type = mode === "changed" ? "any" : "above";
        data[field.name] =
          type === "any"
            ? { type }
            : {
                type,
                value: {
                  number: selector.numeric_threshold?.number?.min ?? 0,
                  active_choice: "number",
                },
              };
      } else {
        throw new Error(
          `Selector ${Object.keys(selector)[0]} not supported in initial form data`
        );
      }
    }
  });
  return data;
};
