import { Ionicons } from "@expo/vector-icons";
import React, { ReactNode, useEffect, useState } from "react";
import {
  ActivityIndicator,
  Dimensions,
  Pressable,
  Modal as RNModal,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from "react-native";

// Types
export interface ModalProps {
  /** Whether the modal dialog is visible or not */
  open?: boolean;
  /** The modal dialog's title */
  title?: ReactNode;
  /** Whether a close (x) button is visible on top right or not */
  closable?: boolean;
  /** Custom close icon */
  closeIcon?: ReactNode;
  /** Whether to close the modal dialog when the mask (area outside the modal) is clicked */
  maskClosable?: boolean;
  /** Centered Modal */
  centered?: boolean;
  /** Width of the modal dialog */
  width?: number | string;
  /** Whether to apply loading visual effect for OK button or not */
  confirmLoading?: boolean;
  /** Text of the OK button */
  okText?: string;
  /** Text of the Cancel button */
  cancelText?: string;
  /** Button type of the OK button */
  okType?: "primary" | "default" | "dashed" | "text" | "link";
  /** Footer content, set as footer={null} when you don't need default buttons */
  footer?: ReactNode | null;
  /** Whether show mask or not */
  mask?: boolean;
  /** The z-index of the Modal */
  zIndex?: number;
  /** Specify a function that will be called when a user clicks the OK button */
  onOk?: (e?: any) => void | Promise<void>;
  /** Specify a function that will be called when a user clicks mask, close button on top right or Cancel button */
  onCancel?: (e?: any) => void;
  /** Callback when the animation ends when Modal is turned on and off */
  afterOpenChange?: (open: boolean) => void;
  /** Specify a function that will be called when modal is closed completely */
  afterClose?: () => void;
  /** Custom className */
  className?: string;
  /** Modal body content */
  children?: ReactNode;
  /** Whether to unmount child components on close */
  destroyOnClose?: boolean;
  /** The ok button props */
  okButtonProps?: any;
  /** The cancel button props */
  cancelButtonProps?: any;
  /** Whether support press esc to close */
  keyboard?: boolean;
}

export interface ConfirmModalProps extends Omit<ModalProps, "open"> {
  /** Type of the confirm modal */
  type?: "info" | "success" | "error" | "warning" | "confirm";
  /** Content */
  content?: ReactNode;
  /** Custom icon */
  icon?: ReactNode;
}

// Modal Component
const Modal: React.FC<ModalProps> & {
  info: (props: ConfirmModalProps) => ModalInstance;
  success: (props: ConfirmModalProps) => ModalInstance;
  error: (props: ConfirmModalProps) => ModalInstance;
  warning: (props: ConfirmModalProps) => ModalInstance;
  confirm: (props: ConfirmModalProps) => ModalInstance;
  useModal: () => [
    {
      info: (props: ConfirmModalProps) => ModalInstance;
      success: (props: ConfirmModalProps) => ModalInstance;
      error: (props: ConfirmModalProps) => ModalInstance;
      warning: (props: ConfirmModalProps) => ModalInstance;
      confirm: (props: ConfirmModalProps) => ModalInstance;
    },
    ReactNode
  ];
} = ({
  open = false,
  title,
  closable = true,
  closeIcon,
  maskClosable = true,
  centered = false,
  width = 520,
  confirmLoading = false,
  okText = "OK",
  cancelText = "Cancel",
  okType = "primary",
  footer,
  mask = true,
  zIndex = 1000,
  onOk,
  onCancel,
  afterOpenChange,
  afterClose,
  className,
  children,
  destroyOnClose = false,
  okButtonProps,
  cancelButtonProps,
  keyboard = true,
}) => {
  const [visible, setVisible] = useState(open);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    setVisible(open);
    if (afterOpenChange) {
      afterOpenChange(open);
    }
  }, [open, afterOpenChange]);

  const handleOk = async () => {
    if (onOk) {
      setLoading(true);
      try {
        await onOk();
        // Không tự động đóng modal - để parent component quyết định
      } catch (error) {
        console.error("Modal onOk error:", error);
      } finally {
        setLoading(false);
      }
    } else {
      setVisible(false);
    }
  };

  const handleCancel = () => {
    if (onCancel) {
      onCancel();
    } else {
      // Nếu không có onCancel, tự động đóng modal
      setVisible(false);
    }
  };

  const handleMaskPress = () => {
    if (maskClosable) {
      handleCancel();
    }
  };

  const handleRequestClose = () => {
    if (keyboard) {
      handleCancel();
    }
  };

  useEffect(() => {
    if (!visible && afterClose) {
      const timer = setTimeout(() => {
        afterClose();
      }, 300); // Wait for animation to complete
      return () => clearTimeout(timer);
    }
  }, [visible, afterClose]);

  const renderFooter = () => {
    if (footer === null) {
      return null;
    }

    if (footer !== undefined) {
      return <View style={styles.footer}>{footer}</View>;
    }

    return (
      <View style={styles.footer}>
        <TouchableOpacity
          style={[styles.button, styles.cancelButton]}
          onPress={handleCancel}
          disabled={loading || confirmLoading}
          {...cancelButtonProps}
        >
          <Text style={styles.cancelButtonText}>{cancelText}</Text>
        </TouchableOpacity>
        <TouchableOpacity
          style={[
            styles.button,
            styles.okButton,
            okType === "primary" && styles.primaryButton,
            (loading || confirmLoading) && styles.disabledButton,
          ]}
          onPress={handleOk}
          disabled={loading || confirmLoading}
          {...okButtonProps}
        >
          {loading || confirmLoading ? (
            <ActivityIndicator color="#fff" size="small" />
          ) : (
            <Text style={styles.okButtonText}>{okText}</Text>
          )}
        </TouchableOpacity>
      </View>
    );
  };

  const modalWidth =
    typeof width === "number" ? width : Dimensions.get("window").width * 0.9;

  return (
    <RNModal
      visible={visible}
      transparent
      animationType="fade"
      onRequestClose={handleRequestClose}
      statusBarTranslucent
    >
      <Pressable
        style={[
          styles.overlay,
          centered && styles.centered,
          { zIndex },
          !mask && styles.noMask,
        ]}
        onPress={handleMaskPress}
      >
        <Pressable
          style={[styles.modal, { width: modalWidth, maxWidth: "90%" }]}
          onPress={(e) => e.stopPropagation()}
        >
          {/* Header */}
          {(title || closable) && (
            <View style={styles.header}>
              {title && (
                <Text style={styles.title} numberOfLines={1}>
                  {title}
                </Text>
              )}
              {closable && (
                <TouchableOpacity
                  style={styles.closeButton}
                  onPress={handleCancel}
                  hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
                >
                  {closeIcon || (
                    <Ionicons name="close" size={24} color="#666" />
                  )}
                </TouchableOpacity>
              )}
            </View>
          )}

          {/* Body */}
          <View style={styles.body}>
            {(!destroyOnClose || visible) && children}
          </View>

          {/* Footer */}
          {renderFooter()}
        </Pressable>
      </Pressable>
    </RNModal>
  );
};

// Confirm Modal Component
const ConfirmModal: React.FC<
  ConfirmModalProps & { visible: boolean; onClose: () => void }
> = ({
  visible,
  onClose,
  type = "confirm",
  title,
  content,
  icon,
  okText = "OK",
  cancelText = "Cancel",
  onOk,
  onCancel,
  ...restProps
}) => {
  const [loading, setLoading] = useState(false);

  const getIcon = () => {
    if (icon !== undefined) return icon;

    const iconProps = { size: 24, style: { marginRight: 12 } };
    switch (type) {
      case "info":
        return (
          <Ionicons name="information-circle" color="#1890ff" {...iconProps} />
        );
      case "success":
        return (
          <Ionicons name="checkmark-circle" color="#52c41a" {...iconProps} />
        );
      case "error":
        return <Ionicons name="close-circle" color="#ff4d4f" {...iconProps} />;
      case "warning":
        return <Ionicons name="warning" color="#faad14" {...iconProps} />;
      default:
        return <Ionicons name="help-circle" color="#1890ff" {...iconProps} />;
    }
  };

  const handleOk = async () => {
    if (onOk) {
      setLoading(true);
      try {
        await onOk();
        onClose();
      } catch (error) {
        console.error("Confirm modal onOk error:", error);
      } finally {
        setLoading(false);
      }
    } else {
      onClose();
    }
  };

  const handleCancel = () => {
    if (onCancel) {
      onCancel();
    }
    onClose();
  };

  return (
    <Modal
      open={visible}
      title={title}
      onOk={handleOk}
      onCancel={type === "confirm" ? handleCancel : undefined}
      okText={okText}
      cancelText={cancelText}
      confirmLoading={loading}
      footer={
        type === "confirm" ? undefined : (
          <View style={styles.footer}>
            <TouchableOpacity
              style={[styles.button, styles.okButton, styles.primaryButton]}
              onPress={handleOk}
              disabled={loading}
            >
              {loading ? (
                <ActivityIndicator color="#fff" size="small" />
              ) : (
                <Text style={styles.okButtonText}>{okText}</Text>
              )}
            </TouchableOpacity>
          </View>
        )
      }
      {...restProps}
    >
      <View style={styles.confirmContent}>
        {getIcon()}
        <Text style={styles.confirmText}>{content}</Text>
      </View>
    </Modal>
  );
};

// Modal Instance
export interface ModalInstance {
  destroy: () => void;
  update: (config: ConfirmModalProps) => void;
}

// Container for imperatively created modals - Not used in React Native
// Static methods will return instance but won't render imperatively
// Use Modal.useModal() hook for proper context support

const createConfirmModal = (config: ConfirmModalProps): ModalInstance => {
  console.warn(
    "Modal static methods are not fully supported in React Native. Please use Modal.useModal() hook for better context support."
  );

  return {
    destroy: () => {
      console.warn(
        "Modal.destroy() called but static modals are not supported in React Native"
      );
    },
    update: (newConfig: ConfirmModalProps) => {
      console.warn(
        "Modal.update() called but static modals are not supported in React Native"
      );
    },
  };
};

// Static methods
Modal.info = (props: ConfirmModalProps) =>
  createConfirmModal({ ...props, type: "info" });
Modal.success = (props: ConfirmModalProps) =>
  createConfirmModal({ ...props, type: "success" });
Modal.error = (props: ConfirmModalProps) =>
  createConfirmModal({ ...props, type: "error" });
Modal.warning = (props: ConfirmModalProps) =>
  createConfirmModal({ ...props, type: "warning" });
Modal.confirm = (props: ConfirmModalProps) =>
  createConfirmModal({ ...props, type: "confirm" });

// useModal hook
Modal.useModal = () => {
  const [modals, setModals] = useState<ReactNode[]>([]);

  const createModal = (
    config: ConfirmModalProps,
    type: ConfirmModalProps["type"]
  ) => {
    const id = `modal-${Date.now()}-${Math.random()}`;

    const destroy = () => {
      setModals((prev) => prev.filter((modal: any) => modal.key !== id));
    };

    const update = (newConfig: ConfirmModalProps) => {
      setModals((prev) =>
        prev.map((modal: any) =>
          modal.key === id ? (
            <ConfirmModal
              key={id}
              visible={true}
              onClose={destroy}
              {...config}
              {...newConfig}
              type={type}
            />
          ) : (
            modal
          )
        )
      );
    };

    const modalElement = (
      <ConfirmModal
        key={id}
        visible={true}
        onClose={destroy}
        {...config}
        type={type}
      />
    );

    setModals((prev) => [...prev, modalElement]);

    return { destroy, update };
  };

  const modalMethods = {
    info: (props: ConfirmModalProps) => createModal(props, "info"),
    success: (props: ConfirmModalProps) => createModal(props, "success"),
    error: (props: ConfirmModalProps) => createModal(props, "error"),
    warning: (props: ConfirmModalProps) => createModal(props, "warning"),
    confirm: (props: ConfirmModalProps) => createModal(props, "confirm"),
  };

  const contextHolder = <>{modals}</>;

  return [modalMethods, contextHolder];
};

// Styles
const styles = StyleSheet.create({
  overlay: {
    flex: 1,
    backgroundColor: "rgba(0, 0, 0, 0.45)",
    justifyContent: "flex-start",
    paddingTop: 100,
    alignItems: "center",
  },
  centered: {
    justifyContent: "center",
    paddingTop: 0,
  },
  noMask: {
    backgroundColor: "transparent",
  },
  modal: {
    backgroundColor: "#fff",
    borderRadius: 8,
    shadowColor: "#000",
    shadowOffset: { width: 0, height: 4 },
    shadowOpacity: 0.15,
    shadowRadius: 12,
    elevation: 8,
    maxHeight: "90%",
  },
  header: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "space-between",
    paddingHorizontal: 24,
    paddingTop: 20,
    paddingBottom: 16,
    borderBottomWidth: 1,
    borderBottomColor: "#f0f0f0",
  },
  title: {
    fontSize: 18,
    fontWeight: "600",
    color: "#000",
    flex: 1,
  },
  closeButton: {
    padding: 4,
    marginLeft: 12,
  },
  body: {
    paddingHorizontal: 24,
    paddingVertical: 20,
  },
  footer: {
    flexDirection: "row",
    justifyContent: "flex-end",
    alignItems: "center",
    paddingHorizontal: 24,
    paddingBottom: 20,
    paddingTop: 12,
    gap: 8,
  },
  button: {
    paddingVertical: 8,
    paddingHorizontal: 16,
    borderRadius: 6,
    minWidth: 70,
    alignItems: "center",
    justifyContent: "center",
    height: 36,
  },
  cancelButton: {
    backgroundColor: "#fff",
    borderWidth: 1,
    borderColor: "#d9d9d9",
  },
  cancelButtonText: {
    color: "#000",
    fontSize: 14,
    fontWeight: "500",
  },
  okButton: {
    backgroundColor: "#1890ff",
  },
  primaryButton: {
    backgroundColor: "#1890ff",
  },
  okButtonText: {
    color: "#fff",
    fontSize: 14,
    fontWeight: "500",
  },
  disabledButton: {
    opacity: 0.6,
  },
  confirmContent: {
    flexDirection: "row",
    alignItems: "flex-start",
  },
  confirmText: {
    flex: 1,
    fontSize: 14,
    color: "#000",
    lineHeight: 22,
  },
});

export default Modal;
