import { ButtonProps } from '@mui/material';
export type ObjectWithId = {
    id?: number | string;
};

// TODO remove duplicate DTOs from golden ui, otherwise they'll be defined twice
// TODO bring over SimpleRequest & PageRequest too, for consistency?

/**
 * State for the current page for pagination. NOTE: Use `PageRequest` for API calls.
 */
export type PageState = {
    /**
     * Page number (starts at 0) for paginated results.
     */
    pageNo: number;

    /**
     * Page size for paginated results (number of rows).
     */
    pageSize: number;
};

/**
 * Paginated API response
 */
export type PageResponse<T> = {
    data: T[];
    pageNo: number;
    pageSize: number;
    totalCount: number;
};

/**
 * Filter definition for narrowing down results from the service.
 */
export type Filter = {
    column: string;
    value: any;
    /**
     * These are the only supported operations for now
     * More can be added in the future, but support may need to be added on the backend
     * (i.e. ILIKE is a POSTGRES operation, the backend converts it to LIKE when using SQLITE)
     */
    operation?: 'ILIKE' | '=' | 'IS DISTINCT FROM' | 'CLOSEST';
};

export type PaginationState = PageState & {
    totalCount: number;
    // searchTerm?: string;
    sortField?: string;
    sortOrder?: 'asc' | 'desc';
};

type LabelWithIcon = {
    icon?: React.ReactElement;
    label: string;
};

export type MenuOption = LabelWithIcon & {
    /**
     * The minimum permission required to access this page (most commonly will be some sort of view permission).
     *
     * If not defined, this nav item will always be rendered in the navigation components regardless of user permissions.
     * If defined, this nav item will be removed the navigation components if the user is missing the permission.
     *
     * @default undefined
     */
    minPermission?: string | string[];

    /**
     * Performs the action when clicked (ex. toggle dark mode). Avoid using this to navigate (use `path` or `externalLink` instead).
     *
     * When `path` or `externalLink` is defined, this onClick will run right before navigating. Use this to handle any non-navigation logic that needs to happen.
     */
    onClick?: () => void; // TODO update this to allow for conditional navigating based on the return value (true = navigate, false = don't navigate)
} & (
        | {
              /**
               * Internal path that this navigation item should navigate to (ex '/home')
               */
              path: string;
              externalLink?: never;
          }
        | {
              /**
               * External path that this navigation item should navigate to (ex 'https://www.google.com')
               */
              externalLink: string;
              path?: never;
          }
        | {
              path?: never;
              externalLink?: never;
          }
    );

export type EnvironmentInfo = {
    env?: string; // ex 'Development'
    isProd?: boolean;
};

/**
 * TableColumn represents a column in a table where `K` represents a property of `T`
 * EXAMPLE: For a table of users, this would be the `TableColumn` defintion for the
 *          phone number column:  TableColumn<User, Phone>.
 *
 * @property {string} label - Label that will display in the Table header for the column
 * @property {string} fieldName - Property name of the object
 * @property {(value: K, object: T, isMobile: boolean) => React.ReactNode} render - customize
 *      how the data is displayed in the column where `value` is the property value. `object`
 *      is the whole object, in case you need to determine styling based on another property
 *      within the object. isMobile in case your styling depends on whether the user is viewing
 *      on a phone vs tablet/desktop
 * @property {string} sortName - (Optional) Passed instead of `fieldName` to onSortChange(fieldName, ...). Useful if you're rendering the same object in 2+ columns and need a way to differentiate when sorting.
 */
export type TableColumn<T, K> = {
    key?: string;
    label?: string;
    fieldName: string;
    render?: (value: K, object: T, isMobile: boolean) => React.ReactNode; // used to customize how the data `obj` is displayed in the table
    sortName?: string;
};

// Sort order for Tables
export type SortOrder = 'asc' | 'desc';

export type TableConfig<T> = {
    [K in keyof T]: TableColumn<T, T[K]>; // columns is an array of TableColumns, where the type of each TableColumn matches one of the properties of T (ex. `User`)
}[keyof T][];

/**
 * Convenience Interface for autocomplete dropdown options
 * @label string displayed in the dropdown
 * @value generic-type value associated with the option
 */
export interface AutocompleteOption<T> {
    label: string;
    value: T;
}

/**
 * Checkbox Option
 *
 * Can be string OR:
 * {
 *      label: string;          // UI label
 *      sublabel?: string;      // Smaller text that appears below UI label. Supplemental/help text.
 *      withTextField?: string; // Displays textfield for additional information needed from user (ex. "Other" checkbox). At mininmum, make sure to pass in `name` property.
 * }
 */
export type CheckboxOption =
    | string
    | {
          label: string;
          sublabel?: string;
          textField?: TextFieldProps;
      };

/**
 * Used for CitationField
 * Represents a citation (web article/attachment/other url)
 */
export type Citation = {
    id: number;
    createdBy?: number;
    updatedBy?: number;
    deletedBy?: number;

    fileName?: string;
    url?: string;
    title: string;
    source?: string; // publisher
    accessedAt?: string | null;
    classification?: string; // public, unclassified
};

/**
 * Used for CitationField
 * Used to represent a (potentially) unsaved Citation (no id defined yet)
 */
export type UnsavedCitation = {
    id?: number;
} & Omit<Citation, 'id'>;

/**
 * Used for CitationField
 * Used to represent a (potentially) unsaved Attachment (same as UnsavedCitation but with a File obj)
 */
export type UnsavedAttachment = {
    file?: File;
} & UnsavedCitation;
