import styled from "styled-components";
import { useEffect, useState } from "react";
import { RequestFormField } from "../../../ticket-fields";
import { Button } from "@zendeskgarden/react-buttons";
import { getColor } from "@zendeskgarden/react-theming";
import { useTranslation } from "react-i18next";
import type { ServiceCatalogItem } from "../../data-types/ServiceCatalogItem";
import { CollapsibleDescription } from "./CollapsibleDescription";
import type { TicketFieldObject } from "../../../ticket-fields/data-types/TicketFieldObject";
import type { CustomObjectRecord } from "../../../ticket-fields/data-types/CustomObjectRecord";
import { useAssetDataFetchers } from "../../../service-catalog/hooks/useAssetDataFetchers";
import type { ITAMAssetOptionObject } from "../../data-types/ITAMAssetOptionObject";
import { Span } from "@zendeskgarden/react-typography";
import { Option } from "@zendeskgarden/react-dropdowns";

const Form = styled.form`
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  gap: ${(props) => props.theme.space.md};

  @media (max-width: ${(props) => props.theme.breakpoints.md}) {
    flex-direction: column;
  }
`;

const FieldsContainer = styled.div`
  flex: 2;
  display: flex;
  flex-direction: column;
  gap: ${(props) => props.theme.space.md};
  margin-inline-end: ${(props) => props.theme.space.xl};

  @media (max-width: ${(props) => props.theme.breakpoints.md}) {
    margin-inline-end: 0;
  }
`;

const ButtonWrapper = styled.div`
  flex: 1;
  margin-inline-start: ${(props) => props.theme.space.xl};
  padding: ${(props) => props.theme.space.lg};
  border: ${(props) => props.theme.borders.sm}
    ${({ theme }) => getColor({ theme, hue: "grey", shade: 300 })};
  height: fit-content;

  @media (max-width: ${(props) => props.theme.breakpoints.md}) {
    position: sticky;
    top: 0;
    background: ${({ theme }) =>
      getColor({ theme, variable: "background.default" })};
    padding: ${(props) => props.theme.space.lg};
    border: none;
    border-top: ${(props) => props.theme.borders.sm}
      ${({ theme }) => getColor({ theme, hue: "grey", shade: 300 })};
    width: 100vw;
    margin-inline-start: 0;
  }
`;

const RightColumn = styled.div`
  flex: 1;
  margin-inline-start: ${(props) => props.theme.space.xl};

  @media (max-width: ${(props) => props.theme.breakpoints.md}) {
    position: sticky;
    bottom: 0;
    margin-inline-start: 0;
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
  }
`;

const LeftColumn = styled.div`
  flex: 2;
  display: flex;
  flex-direction: column;
  gap: ${(props) => props.theme.space.lg};
  margin-inline-end: ${(props) => props.theme.space.xl};
  min-width: 0;

  @media (max-width: ${(props) => props.theme.breakpoints.md}) {
    margin-inline-end: 0;
  }
`;

export const ASSET_TYPE_KEY = "zen:custom_object:standard::itam_asset_type";
export const ASSET_KEY = "zen:custom_object:standard::itam_asset";

type AssetTypeState = {
  ids: string[];
  hidden: boolean;
  ready: boolean;
  description?: string;
  name?: string;
};
type AssetState = {
  ids: string[];
  ready: boolean;
  description?: string;
  name?: string;
};

const isAssetField = (f: TicketFieldObject) =>
  f.relationship_target_type === ASSET_KEY;
const isAssetTypeField = (f: TicketFieldObject) =>
  f.relationship_target_type === ASSET_TYPE_KEY;

interface ItemRequestFormProps {
  requestFields: TicketFieldObject[];
  serviceCatalogItem: ServiceCatalogItem;
  baseLocale: string;
  hasAtMentions: boolean;
  userRole: string;
  userId: number;
  brandId: number;
  defaultOrganizationId: string | null;
  handleChange: (
    field: TicketFieldObject,
    value: string | string[] | boolean | null
  ) => void;
  onSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
}

export function ItemRequestForm({
  requestFields,
  serviceCatalogItem,
  baseLocale,
  hasAtMentions,
  userRole,
  userId,
  brandId,
  defaultOrganizationId,
  handleChange,
  onSubmit,
}: ItemRequestFormProps) {
  const { t } = useTranslation();

  const assetOptionId =
    serviceCatalogItem?.custom_object_fields?.["standard::asset_option"];
  const assetTypeOptionId =
    serviceCatalogItem?.custom_object_fields?.["standard::asset_type_option"];

  const { fetchAssets, fetchAssetTypes } = useAssetDataFetchers(
    assetOptionId,
    assetTypeOptionId
  );

  const [assetTypeState, setAssetTypeState] = useState<AssetTypeState>({
    ids: [],
    hidden: false,
    ready: false,
    description: undefined,
    name: undefined,
  });
  const [assetState, setAssetState] = useState<AssetState>({
    ids: [],
    ready: false,
    description: undefined,
    name: undefined,
  });
  const [isHiddenAssetsType, setIsHiddenAssetsType] = useState(false);

  const hiddenValue =
    assetTypeState.hidden && assetTypeState.ids[0] ? assetTypeState.ids[0] : "";

  useEffect(() => {
    let alive = true;

    const initAssets = async () => {
      try {
        const res = await fetchAssetTypes();
        if (!alive) return;

        const hidden = !!res?.isHiddenAssetsType;
        const raw = res?.assetTypeIds;
        const description = res?.assetTypeDescription;
        const name = res?.assetTypeName;

        let ids: string[] = [];

        if (Array.isArray(raw)) {
          ids = raw.map(String);
        } else if (typeof raw === "string") {
          ids = raw.split(",");
        }

        ids = ids.map((s) => s.trim()).filter(Boolean);

        setAssetTypeState({ ids, hidden, ready: true, description, name });
        setIsHiddenAssetsType(hidden);
      } catch (e) {
        if (!alive) return;
        setAssetTypeState({
          ids: [],
          hidden: false,
          ready: true,
          description: undefined,
          name: undefined,
        });
      }

      try {
        const res = await fetchAssets();
        if (!alive) return;

        const raw = res?.assetIds;
        const description = res?.assetDescription;
        const name = res?.assetName;

        let ids: string[] = [];

        if (typeof raw === "string") {
          ids = raw.split(",");
        } else if (Array.isArray(raw)) {
          ids = raw.map(String);
        }

        ids = ids.map((s) => s.trim()).filter(Boolean);

        setAssetState({ ids, ready: true, description, name });
      } catch (e) {
        if (!alive) return;
        setAssetState({
          ids: [],
          ready: true,
          description: undefined,
          name: undefined,
        });
      }
    };

    initAssets();

    return () => {
      alive = false;
    };
  }, [fetchAssetTypes, fetchAssets, handleChange]);

  const buildLookupFieldOptions = async (
    records: CustomObjectRecord[],
    field: TicketFieldObject
  ): Promise<ITAMAssetOptionObject[]> => {
    if (!Array.isArray(records) || records.length === 0) return [];

    const options: ITAMAssetOptionObject[] = records.map((rec) => {
      const base = {
        name: rec.name,
        value: rec.id,
        serialNumber: rec.custom_object_fields["standard::serial_number"] as
          | string
          | undefined,
      };

      if (rec.custom_object_key === "standard::itam_asset") {
        const fields = (rec.custom_object_fields ?? {}) as {
          "standard::asset_type"?: string;
        };
        return {
          ...base,
          item_asset_type_id: fields["standard::asset_type"] ?? "",
        };
      }
      return { ...base, item_asset_type_id: "" };
    });

    if (isAssetTypeField(field)) {
      if (assetTypeState.hidden) return [];
      if (!assetTypeState.ids?.length) return [];
      return options.filter((o) => assetTypeState.ids.includes(o.value));
    }

    if (isAssetField(field)) {
      let list = options;
      if (assetState.ids?.length) {
        list = list.filter((o) =>
          assetState.ids.includes(o.item_asset_type_id ?? "")
        );
      }
      return list;
    }
    return options.map(({ name, value, serialNumber }) => ({
      name,
      value,
      serialNumber,
    }));
  };

  const renderLookupFieldOption = (option: ITAMAssetOptionObject) => {
    if (option.serialNumber) {
      return (
        <>
          {option.name}
          <Option.Meta>
            <Span hue="grey">
              {t(
                "service-catalog.item.serial-number-label",
                "SN: {{serialNumber}}",
                { serialNumber: option.serialNumber }
              )}
            </Span>
          </Option.Meta>
        </>
      );
    }
    return option.name;
  };

  return (
    <Form onSubmit={onSubmit} noValidate>
      <LeftColumn>
        <CollapsibleDescription
          title={serviceCatalogItem.name}
          description={serviceCatalogItem.description}
          thumbnailUrl={serviceCatalogItem.thumbnail_url}
        />
        <FieldsContainer>
          {requestFields.map((field) => {
            if (isAssetTypeField(field) && isHiddenAssetsType) {
              return (
                <>
                  <input type="hidden" name={field.name} value={hiddenValue} />
                  <input type="hidden" name="isAssetTypeHidden" value="true" />
                </>
              );
            }
            const customField = {
              ...field,
              label: isAssetField(field)
                ? assetState.name || field.label
                : isAssetTypeField(field)
                ? assetTypeState.name || field.label
                : field.label,
              description: isAssetField(field)
                ? assetState.description || field.description
                : isAssetTypeField(field)
                ? assetTypeState.description || field.description
                : field.description,
            };

            return (
              <RequestFormField
                key={field.id}
                field={customField}
                baseLocale={baseLocale}
                hasAtMentions={hasAtMentions}
                userRole={userRole}
                userId={userId}
                brandId={brandId}
                defaultOrganizationId={defaultOrganizationId}
                handleChange={handleChange}
                visibleFields={requestFields}
                buildLookupFieldOptions={buildLookupFieldOptions}
                renderLookupFieldOption={renderLookupFieldOption}
              />
            );
          })}
        </FieldsContainer>
      </LeftColumn>
      <RightColumn>
        <ButtonWrapper>
          <Button isPrimary size="large" isStretched type="submit">
            {t("service-catalog.item.submit-button", "Submit request")}
          </Button>
        </ButtonWrapper>
      </RightColumn>
    </Form>
  );
}
