// ui/src/pages/AppsTab/AppDeploymentPage/hooks/useDeploymentPageState.ts
import { useState, useEffect, useMemo, useRef } from 'react';
import type { ApplicationConfig } from '../../../../api/queries/commands';
import type { App } from '../../../../api/queries/admin/apps';

export interface MonitoringFormState {
  engineLevel: string;
  payloadCaptureMode: string;
  payloadSize: string;
  payloadUnit: string;
  applicationLogLevel: string;
  agentLogLevel: string;
  metricsEnabled: boolean;
  metricsInterval: string;
  samplingRate: string;
  compressSuccess: boolean;
  replayEnabled: boolean;
  routeControlEnabled: boolean;
}

export interface ResourcesFormState {
  memoryLimit: string;
  memoryReserve: string;
  cpuRequest: string;
  cpuLimit: string;
  appPort: string;
  replicas: string;
  deployStrategy: string;
  stripPrefix: boolean;
  sslOffloading: boolean;
  externalRouting: boolean;
  runtimeType: string;
  customArgs: string;
  extraNetworks: string[];
}

export interface VariablesFormState {
  envVars: { key: string; value: string }[];
}

export interface SensitiveKeysFormState {
  sensitiveKeys: string[];
}

export interface DeploymentPageFormState {
  monitoring: MonitoringFormState;
  resources: ResourcesFormState;
  variables: VariablesFormState;
  sensitiveKeys: SensitiveKeysFormState;
}

export const defaultForm: DeploymentPageFormState = {
  monitoring: {
    engineLevel: 'REGULAR',
    payloadCaptureMode: 'BOTH',
    payloadSize: '4',
    payloadUnit: 'KB',
    applicationLogLevel: 'INFO',
    agentLogLevel: 'INFO',
    metricsEnabled: true,
    metricsInterval: '60',
    samplingRate: '1.0',
    compressSuccess: false,
    replayEnabled: true,
    routeControlEnabled: true,
  },
  resources: {
    memoryLimit: '512', memoryReserve: '', cpuRequest: '500', cpuLimit: '',
    appPort: '8080', replicas: '1', deployStrategy: 'blue-green',
    stripPrefix: true, sslOffloading: true, externalRouting: true, runtimeType: 'auto', customArgs: '',
    extraNetworks: [],
  },
  variables: { envVars: [] },
  sensitiveKeys: { sensitiveKeys: [] },
};

export function useDeploymentPageState(
  app: App | null,
  agentConfig: ApplicationConfig | null,
  envDefaults: Record<string, unknown>,
): {
  form: DeploymentPageFormState;
  setForm: React.Dispatch<React.SetStateAction<DeploymentPageFormState>>;
  reset: () => void;
  serverState: DeploymentPageFormState;
} {
  const serverState = useMemo<DeploymentPageFormState>(() => {
    const merged = { ...envDefaults, ...(app?.containerConfig ?? {}) } as Record<string, unknown>;
    return {
      monitoring: {
        engineLevel: (agentConfig?.engineLevel as string) ?? defaultForm.monitoring.engineLevel,
        payloadCaptureMode: (agentConfig?.payloadCaptureMode as string) ?? defaultForm.monitoring.payloadCaptureMode,
        payloadSize: defaultForm.monitoring.payloadSize,
        payloadUnit: defaultForm.monitoring.payloadUnit,
        applicationLogLevel: (agentConfig?.applicationLogLevel as string) ?? defaultForm.monitoring.applicationLogLevel,
        agentLogLevel: (agentConfig?.agentLogLevel as string) ?? defaultForm.monitoring.agentLogLevel,
        metricsEnabled: agentConfig?.metricsEnabled ?? defaultForm.monitoring.metricsEnabled,
        metricsInterval: defaultForm.monitoring.metricsInterval,
        samplingRate: agentConfig?.samplingRate !== undefined
          ? String(agentConfig.samplingRate)
          : defaultForm.monitoring.samplingRate,
        compressSuccess: agentConfig?.compressSuccess ?? defaultForm.monitoring.compressSuccess,
        replayEnabled: defaultForm.monitoring.replayEnabled,
        routeControlEnabled: defaultForm.monitoring.routeControlEnabled,
      },
      resources: {
        memoryLimit: String(merged.memoryLimitMb ?? defaultForm.resources.memoryLimit),
        memoryReserve: merged.memoryReserveMb != null ? String(merged.memoryReserveMb) : defaultForm.resources.memoryReserve,
        cpuRequest: String(merged.cpuRequest ?? defaultForm.resources.cpuRequest),
        cpuLimit: merged.cpuLimit != null ? String(merged.cpuLimit) : defaultForm.resources.cpuLimit,
        appPort: String(merged.appPort ?? defaultForm.resources.appPort),
        replicas: String(merged.replicas ?? defaultForm.resources.replicas),
        deployStrategy: String(merged.deploymentStrategy ?? defaultForm.resources.deployStrategy),
        stripPrefix: merged.stripPathPrefix !== false,
        sslOffloading: merged.sslOffloading !== false,
        externalRouting: merged.externalRouting !== false,
        runtimeType: String(merged.runtimeType ?? defaultForm.resources.runtimeType),
        customArgs: String(merged.customArgs ?? defaultForm.resources.customArgs),
        extraNetworks: Array.isArray(merged.extraNetworks) ? (merged.extraNetworks as string[]) : defaultForm.resources.extraNetworks,
      },
      variables: {
        envVars: merged.customEnvVars
          ? Object.entries(merged.customEnvVars as Record<string, string>).map(([key, value]) => ({ key, value }))
          : [],
      },
      sensitiveKeys: {
        sensitiveKeys: Array.isArray(agentConfig?.sensitiveKeys)
          ? (agentConfig!.sensitiveKeys as string[])
          : [],
      },
    };
  }, [app, agentConfig, envDefaults]);

  const [form, setForm] = useState<DeploymentPageFormState>(serverState);
  const prevServerStateRef = useRef<DeploymentPageFormState>(serverState);

  useEffect(() => {
    // Only overwrite form if the current form value still matches the previous
    // server state (i.e., the user has no local edits). Otherwise preserve
    // user edits through background refetches.
    setForm((current) => {
      const hadLocalEdits =
        JSON.stringify(current) !== JSON.stringify(prevServerStateRef.current);
      prevServerStateRef.current = serverState;
      return hadLocalEdits ? current : serverState;
    });
  }, [serverState]);

  return { form, setForm, reset: () => setForm(serverState), serverState };
}
