import { ContentCopy, Recycling } from "@mui/icons-material";
import { Typography } from "@mui/material";
import { HttpStatusCode } from "axios";
import { useTranslation } from "react-i18next";
import { useParams } from "react-router-dom";
import { toast } from "react-toastify";
import { z } from "zod";

import { Card, ErrorContext } from "../../../common/components/card/Card";
import { CardField } from "../../../common/components/card/CardField";
import { CardAction } from "../../../common/models/card-action";
import { MAX_NAME_LENGTH } from "../../../constants";
import { Token } from "../../../models/Token";
import { http } from "../../../services/http.service";

const fields: CardField<Token>[] = [
	{
		name: "name",
		title: "Name",
	},
	{
		name: "code",
		title: "Code",
		type: "multiline",
		hideFromEditor: true,
	},
];

const validationSchema = z.object({
	name: z.string({
		required_error: "Name is required",
		invalid_type_error: "Name must be a string"
	})
	.min(3, "Name must be at least 3 characters")
	.max(
		MAX_NAME_LENGTH,
		`Name must be less than ${MAX_NAME_LENGTH} characters`
	),
});

export const TokenCardPage = () => {
	const { t } = useTranslation();
	const { organizationId } = useParams();

	if (!organizationId) {
		throw new Error("organizationId is required");
	}

	const defaultValue: Token = {
		id: "",
		name: "",
		code: "",
		organizationId,
	};

	const extraTitle = (model: Token) => {
		return <Typography>{model.name}</Typography>;
	};

	const handleError = (errorContext: ErrorContext) => {
		if (errorContext.status === HttpStatusCode.Conflict) {
			toast.error(t("The same token is already in the system"));
			return true;
		}

		return false;
	};

	const extraActions: CardAction<Token>[] = [
		{
			title: "Regenerate",
			color: "secondary",
			variant: "outlined",
			icon: <Recycling />,
			/**
			 * Regenerates a token and updates the code of the current model
			 * with the new token value. Shows a success toast notification
			 * after successful regeneration.
			 * @param model the token model to regenerate
			 * @returns the updated model with the new token value
			 */
			action: async (model) => {
				const response = await http.put<{ value: string }>(
					`/api/tokens/${model.id}/regenerate`
				);

				model.code = response.value;

				toast.success(t("New token is regenerated success"));

				return model;
			},
		},
		{
			title: "Copy Token",
			color: "secondary",
			variant: "outlined",
			icon: <ContentCopy />,
			action: async (model) => {
				navigator.clipboard.writeText(model.code);

				toast.success(t("The token is copied at swap buffer success."));

				return model;
			},
		},
	];

	return (
		<Card
			defaultValue={defaultValue}
			fields={fields}
			baseUrl="/api/tokens"
			canEdit={false}
			createTitle="Добавление токена"
			editTitle="Редактирование токена"
			viewTitle="Карточка токена"
			validationSchema={validationSchema}
			extraTitle={extraTitle}
			onError={handleError}
			extraActions={extraActions}
			notificationMethodPrefix="TOKENS"
			getModelTitle={(x) => x.name}
			canRemove={true}
		/>
	);
};
