import { type UrlQueryMap } from '@grafana/data';
import { type Status } from '@grafana/schema/apis/dashboard.grafana.app/v2';
import { type ListOptions, type Resource, type ResourceList } from 'app/features/apiserver/types';
import { type DeleteDashboardResponse } from 'app/features/manage-dashboards/types';
import { type AnnotationsPermissions, type SaveDashboardResponseDTO } from 'app/types/dashboard';

import { type SaveDashboardCommand } from '../components/SaveDashboard/types';

/**
 * Represents the format/version of a dashboard for import/export operations.
 * - Classic: Traditional Grafana dashboard JSON (v1 spec without k8s wrapper)
 * - V1Resource: Kubernetes resource with v1 dashboard spec
 * - V2Resource: Kubernetes resource with v2 dashboard spec (new layouts)
 */
export enum ExportFormat {
  Classic = 'classic',
  V1Resource = 'v1-resource',
  V2Resource = 'v2-resource',
}

export type ListDeletedDashboardsOptions = Omit<ListOptions, 'labelSelector'>;

export interface ListDashboardHistoryOptions {
  limit?: number;
  continueToken?: string;
}

export interface DashboardAPI<G, T> {
  /** Get a dashboard with the access control metadata */
  getDashboardDTO(uid: string, params?: UrlQueryMap): Promise<G>;
  /** Save dashboard */
  saveDashboard(options: SaveDashboardCommand<T>): Promise<SaveDashboardResponseDTO>;
  /** Delete a dashboard */
  deleteDashboard(uid: string, showSuccessAlert: boolean): Promise<DeleteDashboardResponse>;
  /** List versions of a dashboard */
  listDashboardHistory(uid: string, options?: ListDashboardHistoryOptions): Promise<ResourceList<T>>;
  /** Get specific versions of a dashboard */
  getDashboardHistoryVersions(uid: string, versions: number[]): Promise<Array<Resource<T>>>;
  /** Restore a dashboard to a previous version */
  restoreDashboardVersion(uid: string, version: number): Promise<SaveDashboardResponseDTO>;
  /** List all deleted dashboards */
  listDeletedDashboards(options: ListDeletedDashboardsOptions): Promise<ResourceList<T>>;
  /**  Restore a deleted dashboard by re-creating it */
  restoreDashboard(dashboard: Resource<T>): Promise<Resource<T>>;
}

// Implemented using /api/dashboards/*
export interface DashboardWithAccessInfo<T> extends Resource<T, Status, 'DashboardWithAccessInfo'> {
  access: {
    url?: string;
    slug?: string;
    canSave?: boolean;
    canEdit?: boolean;
    canDelete?: boolean;
    canShare?: boolean;
    canStar?: boolean;
    canAdmin?: boolean;
    annotationsPermissions?: AnnotationsPermissions;
    isPublic?: boolean;
  }; // TODO...
}

export interface DashboardVersionError extends Error {
  status: number;
  data: {
    // The version which was stored when the dashboard was created / updated.
    // Currently known versions are: 'v2' | 'v2beta1' | 'v1beta1' | 'v0alpha1'
    storedVersion: string;
    message: string;
  };
}

export class DashboardVersionError extends Error {
  constructor(storedVersion: string | undefined, message = 'Dashboard version mismatch') {
    super(message);
    this.name = 'DashboardVersionError';
    this.status = 200;
    this.data = {
      storedVersion: storedVersion ?? 'unknown',
      message,
    };
  }
}
