import Button from "@/components/Low/Button";
import Checkbox from "@/components/Low/Checkbox";
import Input from "@/components/Low/Input";
import Select from "@/components/Low/Select";
import Modal from "@/components/Modal";
import useCodes from "@/hooks/useCodes";
import useDiscounts from "@/hooks/useDiscounts";
import useUser from "@/hooks/useUser";
import useUsers from "@/hooks/useUsers";
import {Discount} from "@/interfaces/paypal";
import {Code, User} from "@/interfaces/user";
import {USER_TYPE_LABELS} from "@/resources/user";
import {createColumnHelper, flexRender, getCoreRowModel, useReactTable} from "@tanstack/react-table";
import axios from "axios";
import clsx from "clsx";
import moment from "moment";
import {useEffect, useState} from "react";
import ReactDatePicker from "react-datepicker";
import {BsPencil, BsTrash} from "react-icons/bs";
import {toast} from "react-toastify";

const columnHelper = createColumnHelper<Discount>();

const DiscountCreator = ({discount, onClose}: {discount?: Discount; onClose: () => void}) => {
	const [percentage, setPercentage] = useState(discount?.percentage);
	const [domain, setDomain] = useState(discount?.domain);
	const [validUntil, setValidUntil] = useState(discount?.validUntil);

	const submit = async () => {
		const body = {percentage, domain, validUntil: validUntil?.toISOString() || undefined};

		if (discount) {
			return axios
				.patch(`/api/discounts/${discount.id}`, body)
				.then(() => {
					toast.success("Discount has been edited successfully!");
					onClose();
				})
				.catch(() => {
					toast.error("Something went wrong, please try again later!");
				});
		}

		return axios
			.post(`/api/discounts`, body)
			.then(() => {
				toast.success("New discount has been created successfully!");
				onClose();
			})
			.catch(() => {
				toast.error("Something went wrong, please try again later!");
			});
	};

	return (
		<div className="flex flex-col gap-8 py-8">
			<div className="w-full grid grid-cols-1 gap-8">
				<div className="flex flex-col gap-3">
					<label className="font-normal text-base text-mti-gray-dim">Domain *</label>
					<div className="flex gap-4 items-center">
						<Input
							defaultValue={domain}
							placeholder="encoach.com"
							name="domain"
							type="text"
							onChange={(e) => setDomain(e.replaceAll("@", ""))}
						/>
					</div>
				</div>
				<div className="flex flex-col gap-3">
					<label className="font-normal text-base text-mti-gray-dim">Percentage (in %) *</label>
					<div className="flex gap-4 items-center">
						<Input
							defaultValue={percentage}
							placeholder="20"
							name="percentage"
							type="number"
							onChange={(e) => setPercentage(parseFloat(e))}
						/>
					</div>
				</div>
				<div className="flex flex-col gap-3 w-full">
					<label className="font-normal text-base text-mti-gray-dim">Valid Until</label>
					<div className="flex gap-4 items-center w-full">
						<ReactDatePicker
							wrapperClassName="w-full z-[900]"
							calendarClassName="z-[900]"
							popperClassName="z-[900]"
							isClearable
							className={clsx(
								"flex min-h-[70px] w-full cursor-pointer justify-center rounded-full border p-6 text-sm font-normal focus:outline-none",
								"hover:border-mti-purple tooltip",
								"transition duration-300 ease-in-out",
							)}
							filterDate={(date) => moment(date).isAfter(new Date())}
							dateFormat="dd/MM/yyyy"
							selected={validUntil}
							onChange={(date) => setValidUntil(date ? moment(date).endOf("day").toDate() : undefined)}
						/>
					</div>
				</div>
			</div>
			<div className="flex w-full justify-end items-center gap-8 mt-8">
				<Button variant="outline" color="red" className="w-full max-w-[200px]" onClick={onClose}>
					Cancel
				</Button>
				<Button className="w-full max-w-[200px]" onClick={submit} disabled={!percentage || !domain}>
					Submit
				</Button>
			</div>
		</div>
	);
};

export default function DiscountList({user}: {user: User}) {
	const [selectedDiscounts, setSelectedDiscounts] = useState<string[]>([]);

	const [isCreating, setIsCreating] = useState(false);
	const [editingDiscount, setEditingDiscount] = useState<Discount>();

	const [filteredDiscounts, setFilteredDiscounts] = useState<Discount[]>([]);

	const {users} = useUsers();
	const {discounts, reload} = useDiscounts();

	useEffect(() => {
		setFilteredDiscounts(discounts);
	}, [discounts]);

	const toggleDiscount = (id: string) => {
		setSelectedDiscounts((prev) => (prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]));
	};

	const toggleAllDiscounts = (checked: boolean) => {
		if (checked) return setSelectedDiscounts(filteredDiscounts.map((x) => x.id));

		return setSelectedDiscounts([]);
	};

	const deleteDiscounts = async (discounts: string[]) => {
		if (!confirm(`Are you sure you want to delete these ${discounts.length} discount(s)?`)) return;

		const params = new URLSearchParams();
		discounts.forEach((code) => params.append("discount", code));

		axios
			.delete(`/api/discounts?${params.toString()}`)
			.then(() => toast.success(`Deleted the discount(s)!`))
			.catch((reason) => {
				if (reason.response.status === 404) {
					toast.error("Discount not found!");
					return;
				}

				if (reason.response.status === 403) {
					toast.error("You do not have permission to delete this discount!");
					return;
				}

				toast.error("Something went wrong, please try again later.");
			})
			.finally(reload);
	};

	const deleteDiscount = async (discount: Discount) => {
		if (!confirm(`Are you sure you want to delete this "${discount.id}" discount?`)) return;

		axios
			.delete(`/api/discounts/${discount.id}`)
			.then(() => toast.success(`Deleted the "${discount.id}" discount`))
			.catch((reason) => {
				if (reason.response.status === 404) {
					toast.error("Code not found!");
					return;
				}

				if (reason.response.status === 403) {
					toast.error("You do not have permission to delete this discount!");
					return;
				}

				toast.error("Something went wrong, please try again later.");
			})
			.finally(reload);
	};

	const defaultColumns = [
		columnHelper.accessor("id", {
			id: "id",
			header: () => (
				<Checkbox
					disabled={filteredDiscounts.length === 0}
					isChecked={selectedDiscounts.length === filteredDiscounts.length && filteredDiscounts.length > 0}
					onChange={(checked) => toggleAllDiscounts(checked)}>
					{""}
				</Checkbox>
			),
			cell: (info) => (
				<Checkbox isChecked={selectedDiscounts.includes(info.getValue())} onChange={() => toggleDiscount(info.getValue())}>
					{""}
				</Checkbox>
			),
		}),
		columnHelper.accessor("id", {
			header: "ID",
			cell: (info) => info.getValue(),
		}),
		columnHelper.accessor("domain", {
			header: "Domain",
			cell: (info) => `@${info.getValue()}`,
		}),
		columnHelper.accessor("percentage", {
			header: "Percentage",
			cell: (info) => `${info.getValue()}%`,
		}),
		columnHelper.accessor("validUntil", {
			header: "Valid Until",
			cell: (info) => (info.getValue() ? moment(info.getValue()).format("DD/MM/YYYY") : ""),
		}),
		{
			header: "",
			id: "actions",
			cell: ({row}: {row: {original: Discount}}) => {
				return (
					<div className="flex gap-4">
						<div
							data-tip="Delete"
							className="cursor-pointer tooltip"
							onClick={() => {
								setEditingDiscount(row.original);
							}}>
							<BsPencil className="hover:text-mti-purple-light transition ease-in-out duration-300" />
						</div>
						<div data-tip="Delete" className="cursor-pointer tooltip" onClick={() => deleteDiscount(row.original)}>
							<BsTrash className="hover:text-mti-purple-light transition ease-in-out duration-300" />
						</div>
					</div>
				);
			},
		},
	];

	const table = useReactTable({
		data: filteredDiscounts,
		columns: defaultColumns,
		getCoreRowModel: getCoreRowModel(),
	});

	const closeModal = () => {
		setIsCreating(false);
		setEditingDiscount(undefined);
		reload();
	};

	return (
		<>
			<Modal
				isOpen={isCreating || !!editingDiscount}
				onClose={closeModal}
				title={editingDiscount ? `Editing ${editingDiscount.id}` : "New Discount"}>
				<DiscountCreator onClose={closeModal} discount={editingDiscount} />
			</Modal>
			<div className="flex items-center justify-end pb-4 pt-1">
				<div className="flex gap-4 items-center">
					<span>{selectedDiscounts.length} code(s) selected</span>
					<Button
						disabled={selectedDiscounts.length === 0}
						variant="outline"
						color="red"
						className="!py-1 px-10"
						onClick={() => deleteDiscounts(selectedDiscounts)}>
						Delete
					</Button>
				</div>
			</div>
			<table className="rounded-xl bg-mti-purple-ultralight/40 w-full">
				<thead>
					{table.getHeaderGroups().map((headerGroup) => (
						<tr key={headerGroup.id}>
							{headerGroup.headers.map((header) => (
								<th className="p-4 text-left" key={header.id}>
									{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
								</th>
							))}
						</tr>
					))}
				</thead>
				<tbody className="px-2">
					{table.getRowModel().rows.map((row) => (
						<tr className="odd:bg-white even:bg-mti-purple-ultralight/40 rounded-lg py-2" key={row.id}>
							{row.getVisibleCells().map((cell) => (
								<td className="px-4 py-2" key={cell.id}>
									{flexRender(cell.column.columnDef.cell, cell.getContext())}
								</td>
							))}
						</tr>
					))}
				</tbody>
			</table>
			<button
				onClick={() => setIsCreating(true)}
				className="w-full py-2 bg-mti-purple-light hover:bg-mti-purple transition ease-in-out duration-300 text-white">
				New Discount
			</button>
		</>
	);
}
