import {
  Box,
  Button,
  Dialog,
  FieldPicker,
  FormField,
  Heading,
  Input,
  InputSynced,
  Label,
  SelectButtonsSynced,
  SelectSynced,
  Switch,
  Text,
  TextButton,
  useGlobalConfig,
  useBase,
} from "@airtable/blocks/ui";
import React, { useState } from "react";
import { FieldType } from "@airtable/blocks/models";
import { Accordion } from "./util.js";

// A UI component for setting a key in the global config.
// key can be a string (for a top level key) or a list of strings (for a nested value)
function InputSetter({ label, description, keyOrPath }) {
  const globalConfig = useGlobalConfig();

  return (
    <FormField label={label} description={description}>
      <InputSynced
        globalConfigKey={keyOrPath}
        disabled={!globalConfig.hasPermissionToSet(keyOrPath)}
      />
    </FormField>
  );
}

function FieldSetter({
  label,
  description,
  keyOrPath,
  tableName,
  ...setterProps
}) {
  const globalConfig = useGlobalConfig();
  const base = useBase();
  const table = base.getTableByNameIfExists(tableName);

  function setField(newField) {
    globalConfig.setAsync(keyOrPath, newField.id);
  }
  // If table is null or undefined, the FieldPicker will not render.
  return (
    <FormField label={label} description={description}>
      <FieldPicker
        table={table}
        field={table.getFieldIfExists(globalConfig.get(keyOrPath))}
        onChange={setField}
        disabled={!globalConfig.hasPermissionToSet(keyOrPath)}
        {...setterProps}
      />
    </FormField>
  );
}

function AddEmailTypeDialog() {
  const [isDialogOpen, setIsDialogOpen] = useState(false);
  const [name, setName] = useState("");
  const globalConfig = useGlobalConfig();

  function save() {
    globalConfig.setAsync(["email_types", name], {});
    setIsDialogOpen(false);
  }
  return (
    <>
      <Button onClick={() => setIsDialogOpen(true)}>Add new email type</Button>
      {isDialogOpen && (
        <Dialog onClose={() => setIsDialogOpen(false)} width="320px">
          <Dialog.CloseButton />
          <Heading>New Email Type</Heading>
          <FormField
            label="Name"
            description="A short descriptive name of the new type of email"
          >
            <Input value={name} onChange={(e) => setName(e.target.value)} />
          </FormField>
          <Button onClick={save}>Save</Button>
        </Dialog>
      )}
    </>
  );
}

function EmailTypeSettings({ emailType }) {
  const globalConfig = useGlobalConfig();

  const audienceOptions = [
    { value: "volunteer", label: "Volunteer" },
    { value: "recipient", label: "Delivery Recipient" },
  ];

  const deliveriesTable = useBase().getTableByNameIfExists("Deliveries");
  const triggerField = deliveriesTable.getFieldIfExists(
    globalConfig.get("trigger_column")
  );

  const stageOptions = triggerField?.options.choices.map((choice) => {
    return {
      value: choice.id,
      label: choice.name,
    };
  });

  function deleteMe() {
    globalConfig.setAsync(["email_types", emailType], undefined);
  }

  return (
    <Box padding={3}>
      <TextButton onClick={deleteMe} icon="trash" style={{ float: "right" }}>
        Delete
      </TextButton>
      <Accordion title={emailType}>
        <InputSetter
          label="Sendgrid Template ID"
          description="Find this in the Sendgrid UI. Looks like d-ea13bf1f408947829fa19779eade8250"
          keyOrPath={["email_types", emailType, "sendgrid_template"]}
        />
        <FormField
          label="Send to..."
          description="Who should this email be sent to?"
        >
          <SelectButtonsSynced
            globalConfigKey={["email_types", emailType, "audience"]}
            options={audienceOptions}
            width="320px"
          />
        </FormField>
        <FormField
          label="Send when..."
          description={`Email will be sent when ${triggerField.name} column is...`}
        >
          <SelectSynced
            globalConfigKey={["email_types", emailType, "stage"]}
            options={stageOptions}
            width="320px"
          />
        </FormField>
      </Accordion>
    </Box>
  );
}

function AddTemplateVariableDialog({ table }) {
  const [isDialogOpen, setIsDialogOpen] = useState(false);
  const [field, setField] = useState("");
  const [sendgrid, setSendgrid] = useState("");
  const globalConfig = useGlobalConfig();

  function save() {
    globalConfig.setAsync(
      ["template_variables", table.name, field.id],
      sendgrid
    );
    setField("");
    setSendgrid("");
    setIsDialogOpen(false);
  }

  return (
    <>
      <Button onClick={() => setIsDialogOpen(true)}>
        Add new template variable
      </Button>
      {isDialogOpen && (
        <Dialog onClose={() => setIsDialogOpen(false)} width="320px">
          <Dialog.CloseButton />
          <FormField
            label="Airtable field"
            description="What field contains the data you want to send to sendgrid?"
          >
            <FieldPicker
              table={table}
              field={field}
              onChange={(newField) => setField(newField)}
            />
          </FormField>
          <FormField
            label="Sendgrid reference"
            description="How does the sengrid template refer to this data?"
          >
            <Input
              value={sendgrid}
              onChange={(e) => setSendgrid(e.target.value)}
            />
          </FormField>
          <Button onClick={save}>Save</Button>
        </Dialog>
      )}
    </>
  );
}

function TableTemplateVariables({ tableName }) {
  const globalConfig = useGlobalConfig();
  if (globalConfig.get(["template_variables", tableName]) === undefined) {
    globalConfig.setAsync(["template_variables", tableName], {});
  }
  const base = useBase();
  const table = base.getTableByNameIfExists(tableName);

  const tableNameToSendgrid = {
    Deliveries: "delivery",
    Volunteers: "volunteer",
  };

  return (
    <Box padding={3}>
      <Text>
        {" "}
        You can use these fields from the {table.name} table in sendgrid{" "}
      </Text>
      <ul>
        {Object.keys(globalConfig.get(["template_variables", table.name])).map(
          (f_id) => {
            const field = table.getFieldIfExists(f_id);
            // this should be deletable
            const sendgridValue = globalConfig.get([
              "template_variables",
              table.name,
              f_id,
            ]);
            const sendgridFormat = `{{${tableNameToSendgrid[tableName]}.${sendgridValue}}}`;
            const removeLink = (
              <TextButton
                onClick={() => {
                  globalConfig.setAsync(
                    ["template_variables", table.name, f_id],
                    undefined
                  );
                }}
              >
                (remove)
              </TextButton>
            );
            return (
              <li key={f_id}>
                {" "}
                {field.name} -> {sendgridFormat} {removeLink}
              </li>
            );
          }
        )}
      </ul>
      <AddTemplateVariableDialog table={table} />
    </Box>
  );
}

export function SettingsComponent({ exit }) {
  const globalConfig = useGlobalConfig();

  if (globalConfig.get("template_variables") === undefined) {
    globalConfig.setAsync("template_variables", {});
  }

  if (globalConfig.get("email_types") === undefined) {
    globalConfig.setAsync("email_types", {});
  }

  return (
    <Box padding={3}>
      <Button variant="primary" onClick={exit} style={{ float: "right" }}>
        Exit settings
      </Button>
      <h1> Settings </h1>
      <p>
        {" "}
        You probably won't need to do anything here unless you're just starting
        out.{" "}
      </p>
      <Accordion title="Global">
        <InputSetter
          label="Organization name"
          description="When people reply to your emails, what is the name they will see?"
          keyOrPath={["reply_to", "name"]}
        />
        <InputSetter
          label="Reply email"
          description="What email address should people use to reply to your emails?"
          keyOrPath={["reply_to", "email"]}
        />
        <InputSetter
          label="Sendgrid proxy token"
          description="This is a secret token that is used to authenticate sending the email"
          keyOrPath="SENDGRID_PROXY_TOKEN"
        />
        <FieldSetter
          label="Trigger column"
          description="Which column should be used to determine whether an email is sent?"
          keyOrPath="trigger_column"
          tableName="Deliveries"
          allowedTypes={[FieldType.SINGLE_SELECT]}
        />
      </Accordion>
      <Accordion title="Email Types">
        <h4>Delivery Emails</h4>
        <Text>
          Here you can configure emails to go out at various stages of a
          delivery. Emails can be set up for both the delivery recipient and the
          volunteer.
        </Text>
        {Object.keys(globalConfig.get("email_types")).map((emailType) => {
          return <EmailTypeSettings key={emailType} emailType={emailType} />;
        })}
        <AddEmailTypeDialog />
        <Box>
          <h4>Volunteer Emails</h4>
          <Text>
            Enable the setting below if you want to send volunteers a welcome
            email when they first sign up.
          </Text>
          <Switch
            value={!!globalConfig.get("enable_volunteer_welcome_email")}
            onChange={(newValue) =>
              globalConfig.setAsync("enable_volunteer_welcome_email", newValue)
            }
            label="Email volunteers on inital signup"
            width="320px"
          />
          {globalConfig.get("enable_volunteer_welcome_email") ? (
            <>
              <Label htmlFor="volunteer-welcome-template-id-input">
                Volunteer welcome email sendgrid template ID
              </Label>
              <Input
                id="volunteer-welcome-template-id-input"
                value={
                  globalConfig.get("volunteer_welcome_email_template_id") || ""
                }
                onChange={(e) =>
                  globalConfig.setAsync(
                    "volunteer_welcome_email_template_id",
                    e.target.value
                  )
                }
                placeholder="Enter Sendgrid Template ID here"
              />
              <FieldSetter
                label="Volunteer name field"
                description="The field containing volunteers names"
                keyOrPath="volunteer_name_field"
                tableName="Volunteers"
              />
            </>
          ) : null}
        </Box>
      </Accordion>
      <Accordion title="Template Variables">
        {["Deliveries", "Volunteers"].map((tableName) => {
          return (
            <TableTemplateVariables key={tableName} tableName={tableName} />
          );
        })}
      </Accordion>
    </Box>
  );
}