import React, { useCallback, useMemo, useState } from "react";
import { useParams } from "react-router-dom";

import CancelIcon from "@mui/icons-material/Cancel";
import CheckCircleIcon from "@mui/icons-material/CheckCircle";

import Card from "../../../components/Card";
import CardActions from "../../../components/Card/CardActions";
import CardCancelButton from "../../../components/Card/CardCancelButton";
import CardContent from "../../../components/Card/CardContent";
import CardFieldCheckbox from "../../../components/Card/CardFieldCheckbox";
import CardFieldSelect from "../../../components/Card/CardFieldSelect";
import CardFieldText from "../../../components/Card/CardFieldText";
import CardHeader from "../../../components/Card/CardHeader";
import CardRow from "../../../components/Card/CardRow";
import CardSaveButton from "../../../components/Card/CardSaveButton";
import { useApi } from "../../../contexts/ApiContext";
import { useI18n } from "../../../contexts/I18nContext";
import { useUser } from "../../../contexts/UserContext";
import { hasPermission } from "../../../util/has_permission";
import { ProductCreated, ProductDetail, ProductItemTypeOption } from "../types/product";

import { ProductPropertyField } from "./ProductPropertyField";

export type ProductCardProps =
  | {
      create: true;
      product?: ProductDetail;
      onCreated: (product: ProductCreated) => void;
      onUpdated?: never;
      itemTypes: ProductItemTypeOption[];
    }
  | {
      create?: false;
      product: ProductDetail;
      onCreated?: never;
      onUpdated: (product: ProductDetail) => void;
      itemTypes: ProductItemTypeOption[];
    };

export interface ProductCardFormValues {
  number: string;
  item_type: string;
  is_active: string;
  name: string;
  description: string;
}

export const ProductCard: React.FC<ProductCardProps> = ({
  product,
  create,
  onCreated,
  onUpdated,
  itemTypes,
}) => {
  const params = useParams();
  const api = useApi();
  const { t } = useI18n();
  const { user } = useUser();
  const canCreate = useMemo(() => hasPermission(user, "pim.add_product"), [user]);
  const canChange = useMemo(() => hasPermission(user, "pim.change_product"), [user]);

  product ??= {
    id: 0,
    name: "",
    description: "",
    item_type: "",
    number: "",
    is_active: true,
  } as ProductDetail;

  const [productItemType, setProductItemType] = useState<ProductItemTypeOption | undefined>(
    undefined,
  );
  const productPropertiesList = productItemType ? productItemType.product_properties : [];

  const productPropertiesRows = productPropertiesList.reduce<(typeof productPropertiesList)[]>(
    (rows, prop, index) => {
      if (index % 2 === 0) rows.push([prop]);
      else rows[rows.length - 1].push(prop);
      return rows;
    },
    [],
  );

  const handleSave = useCallback(
    async ({ is_active, ...values }: ProductCardFormValues) => {
      if (create != null) {
        const action = api.operations["pim.product:create"];
        if (!action) {
          throw new Error('Invalid action "pim.product:create".');
        }

        const productData: Record<string, unknown> = {};
        const productProperties: Record<string, unknown> = {};

        for (const [key, value] of Object.entries(values)) {
          if (key.startsWith("properties.")) {
            const propertyName = key.replace("properties.", "");
            productProperties[propertyName] = value;
          } else {
            productData[key] = value;
          }
        }

        const response = await action.call({
          params,
          body: {
            is_active: is_active == "on",
            ...productData,
            properties: productProperties,
          },
        });

        if (response.ok) {
          const createdProduct = await response.json();
          onCreated?.(createdProduct);
          return t("Product created successfully.");
        } else {
          console.error("[PRODUCT_CARD]", response);
          throw new Error("creating product.");
        }
      } else {
        const action = api.operations["pim.product:update"];
        if (!action) {
          throw new Error('Invalid action "pim.product:update".');
        }

        const response = await action.call({
          params,
          body: {
            is_active: is_active == "on",
            ...values,
          },
        });

        if (response.ok) {
          const updatedProduct = await response.json();
          onUpdated?.(updatedProduct);
          return t("Product updated successfully.");
        } else {
          console.error("[PRODUCT_CARD]", response);
          throw new Error("updating product fields.");
        }
      }
    },
    [api, params, create, onCreated, onUpdated, t],
  );

  return (
    <Card
      alwaysEditable={create && canCreate}
      columns={3}
      defaultEditing={create && canCreate}
      isEditable={(create && canCreate) || (!create && canChange)}
      onSubmit={handleSave}
    >
      <CardHeader title={t("Product")} />

      <CardContent>
        <CardRow>
          <CardFieldText
            formName="number"
            label={t("Product number")}
            required={true}
            value={product.number}
          />

          <CardFieldSelect
            formName="item_type"
            label={t("Type")}
            options={itemTypes.map((itemType) => ({ id: itemType.name, label: itemType.name }))}
            required={true}
            size={1}
            value={
              product.item_type ? { id: product.item_type, label: product.item_type } : undefined
            }
            onUpdated={(value) => {
              const selectedItemType = itemTypes.find((itemType) => itemType.name == value);
              setProductItemType(selectedItemType);
            }}
          />

          <CardFieldCheckbox
            formName="is_active"
            label={t("Active")}
            noValue={<CancelIcon color="error" fontSize="small" />}
            size={1}
            value={product.is_active}
            yesValue={<CheckCircleIcon color="success" fontSize="small" />}
          />
        </CardRow>

        <CardRow>
          <CardFieldText
            formName="name"
            label={t("Name")}
            required={true}
            size={3}
            value={product.name}
          />
        </CardRow>
        <CardRow>
          <CardFieldText
            formName="description"
            label={t("Description")}
            size={3}
            value={product.description}
          />
        </CardRow>
      </CardContent>

      {create && productPropertiesRows.length > 0 && (
        <>
          <CardHeader title={t("Properties")} />

          <CardContent>
            {productPropertiesRows.map((row, index) => (
              <CardRow key={index}>
                {row.map((prop) => (
                  <ProductPropertyField
                    key={`properties.${prop.name}`}
                    formName={`properties.${prop.name}`}
                    property={prop}
                    value={undefined}
                  />
                ))}
              </CardRow>
            ))}
          </CardContent>
        </>
      )}

      {(canChange || canCreate) && (
        <CardActions>
          {!create && <CardCancelButton />}
          <CardSaveButton label={create ? "Create" : "Save"} />
        </CardActions>
      )}
    </Card>
  );
};
