import { useEffect, useState } from "react"
import { renderToStaticMarkup } from "react-dom/server"
import services from "@/data/services.json"
import Code from "./Code"
import {
  Homepage,
  HomepageEmail,
  HomepageEmailOrProconnect,
  HomepageProconnect,
} from "@gouvfr-lasuite/integration"

const defaultFormData = {
  serviceId: "",
  serviceName: "Service",
  tagline: "**Service**, un outil sécurisé <br>pour les agents de l'État",
  entity: "Gouvernement",
  homepageType: "proconnect",
}

const homepageTypes = {
  proconnect: {
    label: "ProConnect uniquement",
    importCode: "HomepageProconnect",
    componentCode: `<HomepageProconnect url="~~replace~~" />`,
    Component: <HomepageProconnect url="~~replace~~" />,
  },
  "email-or-proconnect": {
    label: "E-mail + ProConnect",
    importCode: "HomepageEmailOrProconnect",
    componentCode: `<HomepageEmailOrProconnect proconnectUrl="~~replace~~" emailForm={{ action: "~~replace~~" }} />`,
    Component: (
      <HomepageEmailOrProconnect
        proconnectUrl="~~replace~~"
        emailForm={{ action: "~~replace~~" }}
      />
    ),
  },
  email: {
    label: "E-mail uniquement",
    importCode: "HomepageEmail",
    componentCode: `<HomepageEmail action="~~replace~~" />`,
    Component: <HomepageEmail action="~~replace~~" />,
  },
  custom: {
    label: "Autre",
    importCode: null,
    componentCode: `~~replace~~`,
    Component: null,
  },
}

export default function HomepageGenerator() {
  const [codeData, setCodeData] = useState<any>(defaultFormData)

  return (
    <div style={{ margin: "1.5rem 0" }}>
      <form
        className="react-form not-content"
        onChange={(e) => {
          const formData = new FormData(e.currentTarget)
          setCodeData({
            ...Object.fromEntries(formData),
            serviceId:
              formData.get("serviceId") && formData.get("serviceId") !== "other"
                ? formData.get("serviceId")
                : undefined,
          })
        }}
      >
        <div className="react-form-input">
          <label htmlFor="serviceId">Service</label>
          <select
            name="serviceId"
            id="serviceId"
            defaultValue={defaultFormData.serviceId}
            onChange={(e) => {
              const serviceId = e.currentTarget.value
              const service = services.find((service) => service.id === serviceId)
              ;(document.querySelector("#tagline") as HTMLInputElement).value = (
                service || defaultFormData
              ).tagline
              ;(document.querySelector("#entity") as HTMLInputElement).value = (
                service || defaultFormData
              ).entity
              ;(document.querySelector("#serviceName") as HTMLInputElement).value = service
                ? service.name
                : defaultFormData.serviceName
              ;(document.querySelector("#homepageType") as HTMLInputElement).value = (
                service || defaultFormData
              ).homepageType
            }}
          >
            <option value="">Choisir votre service pour pré-remplir les champs</option>
            {services.map((service) => (
              <option key={service.id} value={service.id}>
                {service.name}
              </option>
            ))}
            <option value="other">Autre…</option>
          </select>
        </div>

        <div className="react-form-input">
          <label htmlFor="serviceName">Nom du service</label>
          <input
            type="text"
            name="serviceName"
            id="serviceName"
            defaultValue={defaultFormData.serviceName}
          />
        </div>

        <input type="hidden" name="entity" id="entity" defaultValue={defaultFormData.entity} />

        <div className="react-form-input">
          <label htmlFor="tagline">
            Phrase d'accroche
            <span>
              Mettre le texte entre ** pour l'écrire en gras, usage de <code>&lt;br&gt;</code>{" "}
              possible
            </span>
          </label>
          <input type="text" name="tagline" id="tagline" defaultValue={defaultFormData.tagline} />
        </div>

        <div className="react-form-input">
          <label htmlFor="homepageType">Type de connexion</label>
          <select name="homepageType" id="homepageType">
            <option value="">Choisir…</option>
            {Object.keys(homepageTypes).map((key) => (
              <option key={key} value={key}>
                {homepageTypes[key].label}
              </option>
            ))}
          </select>
        </div>
      </form>

      {!!codeData && (
        <>
          <div>
            <h2 style={{ marginTop: "1.5em" }}>Code React correspondant</h2>
            <Code language="jsx">{getReactMarkup(codeData)}</Code>
          </div>

          <div>
            <h2 style={{ marginTop: "1.5em" }}>Code HTML correspondant</h2>
            <Code language="html" fixedHeight>
              {getHTMLMarkup(codeData)}
            </Code>
          </div>
        </>
      )}
    </div>
  )
}

const getReactMarkup = (codeData: any) => {
  return `import { Homepage${
    codeData.homepageType && homepageTypes[codeData.homepageType].importCode
      ? `, ${homepageTypes[codeData.homepageType].importCode}`
      : ""
  } } from "@gouvfr-lasuite/integration"

export default function MyHomepage() {
  return (
    <Homepage
      lasuiteApiUrl="${import.meta.env.PUBLIC_LASUITE_API_URL}"
      entity="${codeData.entity}"
      tagline="${codeData.tagline}"
      serviceName="${codeData.serviceName}" ${
        !!codeData.serviceId
          ? `
      serviceId="${codeData.serviceId}"`
          : ""
      }
      logo="~~replace~~"
      homepageUrl="/"
      footerOptions={{
        description: "Un service de la Direction interministérielle du numérique",
        sitemapUrl: "~~replace~~",
        a11yUrl: "~~replace~~",
        a11yLevel: "~~replace~~",
        termsUrl: "~~replace~~",
        privacyUrl: "~~replace~~",
      }}
    >
      ${codeData.homepageType ? homepageTypes[codeData.homepageType].componentCode : ""}
    </Homepage>
  )
}`
}

const getHTMLMarkup = (codeData: any) => {
  const Component = (
    <Homepage
      lasuiteApiUrl={import.meta.env.PUBLIC_LASUITE_API_URL}
      entity={codeData.entity}
      tagline={codeData.tagline}
      serviceName={codeData.serviceName}
      serviceId={codeData.serviceId}
      logo={
        codeData.serviceId
          ? `${import.meta.env.PUBLIC_LASUITE_API_URL}/api/logos/v1/${codeData.serviceId}.svg`
          : "~~replace~~"
      }
      homepageUrl="/"
      footerOptions={{
        description: "Un service de la Direction interministérielle du numérique",
        sitemapUrl: "~~replace~~",
        a11yUrl: "~~replace~~",
        a11yLevel: "~~replace~~" as "non compliant",
        termsUrl: "~~replace~~",
        privacyUrl: "~~replace~~",
      }}
    >
      {codeData.homepageType ? homepageTypes[codeData.homepageType].Component : ""}
    </Homepage>
  )
  const markup = renderToStaticMarkup(Component)
  if (typeof window === "undefined") {
    return markup
  }
  const div = document.createElement("div")
  div.innerHTML = markup
  return reIndent(div, 0).innerHTML.trim()
}

// https://stackoverflow.com/a/26361620/257559
const reIndent = (node: Element, level: number) => {
  const indentBefore = new Array(level++ + 1).join("  ")
  const indentAfter = new Array(level - 1).join("  ")
  let textNode: Text

  for (let i = 0; i < node.children.length; i++) {
    textNode = document.createTextNode("\n" + indentBefore)
    node.insertBefore(textNode, node.children[i])

    reIndent(node.children[i], level)

    if (node.lastElementChild == node.children[i]) {
      textNode = document.createTextNode("\n" + indentAfter)
      node.appendChild(textNode)
    }
  }

  return node
}
