import {
  k8sUpdate,
  k8sGet,
  k8sDelete,
  K8sModel,
  K8sResourceKind,
} from '@openshift-console/dynamic-plugin-sdk';

const RESOURCE_LIMITS_ANNOTATION = 'devns.openshift.io/resource-limits';

const NamespaceModel: K8sModel = {
  apiGroup: '',
  apiVersion: 'v1',
  kind: 'Namespace',
  plural: 'namespaces',
  abbr: 'NS',
  label: 'Namespace',
  labelPlural: 'Namespaces',
};

const ResourceQuotaModel: K8sModel = {
  apiGroup: '',
  apiVersion: 'v1',
  kind: 'ResourceQuota',
  plural: 'resourcequotas',
  abbr: 'RQ',
  label: 'Resource Quota',
  labelPlural: 'Resource Quotas',
};

const PodModel: K8sModel = {
  apiGroup: '',
  apiVersion: 'v1',
  kind: 'Pod',
  plural: 'pods',
  abbr: 'P',
  label: 'Pod',
  labelPlural: 'Pods',
};

interface ResourceQuota extends K8sResourceKind {
  spec: {
    hard: {
      'limits.cpu'?: string;
      'limits.memory'?: string;
      'requests.cpu'?: string;
      'requests.memory'?: string;
      [key: string]: string | undefined;
    };
  };
}

interface PodList extends K8sResourceKind {
  items: K8sResourceKind[];
}

export const pauseNamespace = async (namespace: string) => {
  try {
    // Get current namespace
    const ns = await k8sGet<K8sResourceKind>({
      model: NamespaceModel,
      name: namespace,
    });

    if (!ns?.metadata) {
      throw new Error('Invalid namespace resource');
    }

    // Store current resource limits in annotation
    const resourceQuotas = await k8sGet<ResourceQuota>({
      model: ResourceQuotaModel,
      name: '', // We'll need to handle getting the actual quota name
      ns: namespace,
    });

    if (!resourceQuotas?.metadata || !resourceQuotas?.spec) {
      throw new Error('Invalid resource quota');
    }

    // Save current quotas in annotation
    const nsWithAnnotation: K8sResourceKind = {
      ...ns,
      metadata: {
        ...ns.metadata,
        annotations: {
          ...(ns.metadata.annotations || {}),
          [RESOURCE_LIMITS_ANNOTATION]: JSON.stringify(resourceQuotas),
        },
      },
    };

    await k8sUpdate({
      model: NamespaceModel,
      data: nsWithAnnotation,
    });

    // Set resource quotas to 0
    const updatedQuotas: ResourceQuota = {
      ...resourceQuotas,
      spec: {
        ...resourceQuotas.spec,
        hard: {
          'limits.cpu': '0',
          'limits.memory': '0',
          'requests.cpu': '0',
          'requests.memory': '0',
        },
      },
    };

    await k8sUpdate({
      model: ResourceQuotaModel,
      data: updatedQuotas,
    });

    // Delete all pods
    const pods = await k8sGet<PodList>({
      model: PodModel,
      ns: namespace,
    });

    if (pods?.items) {
      await Promise.all(
        pods.items.map((pod) =>
          k8sDelete({
            model: PodModel,
            resource: pod,
          }),
        ),
      );
    }

    return true;
  } catch (error) {
    console.error('Error pausing namespace:', error);
    throw error;
  }
};

export const unpauseNamespace = async (namespace: string) => {
  try {
    // Get namespace
    const ns = await k8sGet<K8sResourceKind>({
      model: NamespaceModel,
      name: namespace,
    });

    if (!ns?.metadata?.annotations) {
      throw new Error('Namespace metadata or annotations not found');
    }

    // Get stored resource limits
    const storedLimits = ns.metadata.annotations[RESOURCE_LIMITS_ANNOTATION];
    if (!storedLimits) {
      throw new Error('No stored resource limits found');
    }

    const resourceQuotas: ResourceQuota = JSON.parse(storedLimits);

    // Restore resource quotas
    await k8sUpdate({
      model: ResourceQuotaModel,
      data: resourceQuotas,
    });

    // Remove stored limits annotation
    const { [RESOURCE_LIMITS_ANNOTATION]: removed, ...remainingAnnotations } = ns.metadata.annotations;
    const nsWithoutAnnotation: K8sResourceKind = {
      ...ns,
      metadata: {
        ...ns.metadata,
        annotations: remainingAnnotations,
      },
    };

    await k8sUpdate({
      model: NamespaceModel,
      data: nsWithoutAnnotation,
    });

    return true;
  } catch (error) {
    console.error('Error unpausing namespace:', error);
    throw error;
  }
};
